initial commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/bin
|
||||
24
gradle.properties
Normal file
24
gradle.properties
Normal file
@@ -0,0 +1,24 @@
|
||||
## Dependecies Version
|
||||
|
||||
# Logging
|
||||
log4jVersion = 1.2.17
|
||||
slf4jVersion = 1.6.6
|
||||
|
||||
# Common libraries
|
||||
springVersion = 3.1.4.RELEASE
|
||||
springDataVersion = 1.5.0.RELEASE
|
||||
jacksonVersion = 1.8.8
|
||||
|
||||
# Testing
|
||||
junitVersion = 4.8.1
|
||||
mockitoVersion = 1.8.5
|
||||
|
||||
# Drivers
|
||||
datastaxVersion = 2.0.0-beta2
|
||||
cassandraVersion = 1.2.0
|
||||
nettyVersion = 3.6.2.Final
|
||||
|
||||
# --------------------
|
||||
# Project wide version
|
||||
# --------------------
|
||||
version=2.0.0.BUILD-SNAPSHOT
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
6
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
6
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#Wed Oct 10 20:59:12 EEST 2012
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=http\://services.gradle.org/distributions/gradle-1.2-bin.zip
|
||||
164
gradlew
vendored
Executable file
164
gradlew
vendored
Executable file
@@ -0,0 +1,164 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn ( ) {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die ( ) {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
esac
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
||||
if $cygwin ; then
|
||||
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
fi
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/"
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED"
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
90
gradlew.bat
vendored
Normal file
90
gradlew.bat
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
63
maven.gradle
Normal file
63
maven.gradle
Normal file
@@ -0,0 +1,63 @@
|
||||
apply plugin: 'maven'
|
||||
|
||||
ext.optionalDeps = []
|
||||
ext.providedDeps = []
|
||||
|
||||
ext.optional = { optionalDeps << it }
|
||||
ext.provided = { providedDeps << it }
|
||||
|
||||
install {
|
||||
repositories.mavenInstaller {
|
||||
customizePom(pom, project)
|
||||
}
|
||||
}
|
||||
|
||||
def customizePom(pom, gradleProject) {
|
||||
pom.whenConfigured { generatedPom ->
|
||||
// respect 'optional' and 'provided' dependencies
|
||||
gradleProject.optionalDeps.each { dep ->
|
||||
generatedPom.dependencies.find { it.artifactId == dep.name }?.optional = true
|
||||
}
|
||||
gradleProject.providedDeps.each { dep ->
|
||||
generatedPom.dependencies.find { it.artifactId == dep.name }?.scope = 'provided'
|
||||
}
|
||||
|
||||
// eliminate test-scoped dependencies (no need in maven central poms)
|
||||
generatedPom.dependencies.removeAll { dep ->
|
||||
dep.scope == 'test'
|
||||
}
|
||||
|
||||
// add all items necessary for maven central publication
|
||||
generatedPom.project {
|
||||
name = gradleProject.description
|
||||
description = gradleProject.description
|
||||
url = 'http://github.com/shvid/spring-data-cassandra'
|
||||
organization {
|
||||
name = 'Mirantis'
|
||||
url = 'http://www.mirantis.com/spring-data/cassnadra'
|
||||
}
|
||||
licenses {
|
||||
license {
|
||||
name 'The Apache Software License, Version 2.0'
|
||||
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
|
||||
distribution 'repo'
|
||||
}
|
||||
}
|
||||
scm {
|
||||
url = 'http://github.com/shvid/spring-data-cassandra'
|
||||
connection = 'scm:git:git://github.com/shvid/spring-data-cassandra'
|
||||
developerConnection = 'scm:git:git://github.com/shvid/spring-data-cassandra'
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id = 'shvid'
|
||||
name = 'Alex Shvid'
|
||||
email = 'aschwid@mirantis.com'
|
||||
properties {
|
||||
twitter = 'alexshvid'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,10 @@
|
||||
Spring Data Cassandra
|
||||
=====================
|
||||
|
||||
This is a Spring Data subproject for Cassandra that uses the binary CQL3 protocol via
|
||||
the official DataStax 2.0 Java driver (https://github.com/datastax/java-driver).
|
||||
|
||||
Supports native CQL3 queries in Spring Repositories.
|
||||
|
||||
For now, you can get and start a local Cassandra instance via the \*n\*x script `test-support/get-and-start-cassandra`.
|
||||
It stores the cassandra process id in the file `.cassandra/dist/dsc-cassandra-x.y.z/cassandra.pid`, where `x.y.z` is the latest version of Cassandra. You can use this process id to stop Cassandra via ``kill `cat .cassandra/dist/dsc-cassandra-x.y.z/cassandra.pid` ``.
|
||||
@@ -0,0 +1,6 @@
|
||||
#NOTE: This is an internal implementation file, its format can be changed without prior notice.
|
||||
#Sun Feb 24 13:09:33 AMT 2013
|
||||
cassandra-driver-core-1.0.0-beta1-javadoc.jar>=
|
||||
cassandra-driver-core-1.0.0-beta1.jar>=
|
||||
cassandra-driver-core-1.0.0-beta1.pom>=
|
||||
cassandra-driver-core-1.0.0-beta1-sources.jar>=
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,126 @@
|
||||
<!--
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License. See accompanying LICENSE file.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.datastax.cassandra</groupId>
|
||||
<artifactId>cassandra-driver-parent</artifactId>
|
||||
<version>1.0.0-beta1</version>
|
||||
</parent>
|
||||
<artifactId>cassandra-driver-core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>DataStax Java Driver for Apache Cassandra - Core</name>
|
||||
<description>A driver for Apache Cassandra 1.2+ that works exclusively with the Cassandra Query Language version 3 (CQL3) and Cassandra's binary protocol.</description>
|
||||
<url>https://github.com/datastax/java-driver</url>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty</artifactId>
|
||||
<version>3.6.2.Final</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>13.0.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.cassandra</groupId>
|
||||
<artifactId>cassandra-thrift</artifactId>
|
||||
<version>1.2.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.thrift</groupId>
|
||||
<artifactId>libthrift</artifactId>
|
||||
<version>0.7.0</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-core-asl</artifactId>
|
||||
<version>1.4.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.yammer.metrics</groupId>
|
||||
<artifactId>metrics-core</artifactId>
|
||||
<version>2.2.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>default</id>
|
||||
<properties>
|
||||
<env>default</env>
|
||||
<cassandra.version>1.2.0</cassandra.version>
|
||||
</properties>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<configuration>
|
||||
<useFile>false</useFile>
|
||||
<systemPropertyVariables>
|
||||
<cassandra.version>${cassandra.version}</cassandra.version>
|
||||
<ipprefix>${ipprefix}</ipprefix>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache 2</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
<comments>Apache License Version 2.0</comments>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:git@github.com:datastax/java-driver.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:datastax/java-driver.git</developerConnection>
|
||||
<url>https://github.com/datastax/java-driver</url>
|
||||
</scm>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Various</name>
|
||||
<organization>DataStax</organization>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<groupId>com.datastax.cassandra</groupId>
|
||||
<artifactId>cassandra-driver-core</artifactId>
|
||||
<versioning>
|
||||
<release>1.0.0-beta1</release>
|
||||
<versions>
|
||||
<version>1.0.0-beta1</version>
|
||||
</versions>
|
||||
<lastUpdated>20130224090933</lastUpdated>
|
||||
</versioning>
|
||||
</metadata>
|
||||
@@ -0,0 +1,3 @@
|
||||
#NOTE: This is an internal implementation file, its format can be changed without prior notice.
|
||||
#Sun Feb 24 13:09:33 AMT 2013
|
||||
cassandra-driver-examples-parent-1.0.0-beta1.pom>=
|
||||
@@ -0,0 +1,54 @@
|
||||
<!--
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License. See accompanying LICENSE file.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.datastax.cassandra</groupId>
|
||||
<artifactId>cassandra-driver-parent</artifactId>
|
||||
<version>1.0.0-beta1</version>
|
||||
</parent>
|
||||
<artifactId>cassandra-driver-examples-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<name>DataStax Java Driver for Apache Cassandra Examples</name>
|
||||
<description>A collection of examples to demonstrate DataStax Java Driver for Apache Cassandra.</description>
|
||||
<url>https://github.com/datastax/java-driver</url>
|
||||
|
||||
<modules>
|
||||
<module>stress</module>
|
||||
</modules>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache 2</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
<comments>Apache License Version 2.0</comments>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:git@github.com:datastax/java-driver.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:datastax/java-driver.git</developerConnection>
|
||||
<url>https://github.com/datastax/java-driver</url>
|
||||
</scm>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Various</name>
|
||||
<organization>DataStax</organization>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<groupId>com.datastax.cassandra</groupId>
|
||||
<artifactId>cassandra-driver-examples-parent</artifactId>
|
||||
<versioning>
|
||||
<release>1.0.0-beta1</release>
|
||||
<versions>
|
||||
<version>1.0.0-beta1</version>
|
||||
</versions>
|
||||
<lastUpdated>20130224090933</lastUpdated>
|
||||
</versioning>
|
||||
</metadata>
|
||||
@@ -0,0 +1,6 @@
|
||||
#NOTE: This is an internal implementation file, its format can be changed without prior notice.
|
||||
#Sun Feb 24 13:09:34 AMT 2013
|
||||
cassandra-driver-examples-stress-1.0.0-beta1-javadoc.jar>=
|
||||
cassandra-driver-examples-stress-1.0.0-beta1.jar>=
|
||||
cassandra-driver-examples-stress-1.0.0-beta1.pom>=
|
||||
cassandra-driver-examples-stress-1.0.0-beta1-sources.jar>=
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,89 @@
|
||||
<!--
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License. See accompanying LICENSE file.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.datastax.cassandra</groupId>
|
||||
<artifactId>cassandra-driver-examples-parent</artifactId>
|
||||
<version>1.0.0-beta1</version>
|
||||
</parent>
|
||||
<artifactId>cassandra-driver-examples-stress</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>DataStax Java Driver for Apache Cassandra Examples - Stress</name>
|
||||
<description>A stress test example for DataStax Java Driver for Apache Cassandra.</description>
|
||||
<url>https://github.com/datastax/java-driver</url>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.datastax.cassandra</groupId>
|
||||
<artifactId>cassandra-driver-core</artifactId>
|
||||
<version>1.0.0-beta1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.yammer.metrics</groupId>
|
||||
<artifactId>metrics-core</artifactId>
|
||||
<version>2.2.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.sf.jopt-simple</groupId>
|
||||
<artifactId>jopt-simple</artifactId>
|
||||
<version>4.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>com.datastax.driver.stress.Stress</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache 2</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
<comments>Apache License Version 2.0</comments>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:git@github.com:datastax/java-driver.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:datastax/java-driver.git</developerConnection>
|
||||
<url>https://github.com/datastax/java-driver</url>
|
||||
</scm>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Various</name>
|
||||
<organization>DataStax</organization>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<groupId>com.datastax.cassandra</groupId>
|
||||
<artifactId>cassandra-driver-examples-stress</artifactId>
|
||||
<versioning>
|
||||
<release>1.0.0-beta1</release>
|
||||
<versions>
|
||||
<version>1.0.0-beta1</version>
|
||||
</versions>
|
||||
<lastUpdated>20130224090934</lastUpdated>
|
||||
</versioning>
|
||||
</metadata>
|
||||
@@ -0,0 +1,3 @@
|
||||
#NOTE: This is an internal implementation file, its format can be changed without prior notice.
|
||||
#Sun Feb 24 13:09:29 AMT 2013
|
||||
cassandra-driver-parent-1.0.0-beta1.pom>=
|
||||
@@ -0,0 +1,126 @@
|
||||
<!--
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License. See accompanying LICENSE file.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.datastax.cassandra</groupId>
|
||||
<artifactId>cassandra-driver-parent</artifactId>
|
||||
<version>1.0.0-beta1</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>DataStax Java Driver for Apache Cassandra</name>
|
||||
<description>A driver for Apache Cassandra 1.2+ that works exclusively with the Cassandra Query Language version 3 (CQL3) and Cassandra's binary protocol.</description>
|
||||
<url>https://github.com/datastax/java-driver</url>
|
||||
|
||||
<modules>
|
||||
<module>driver-core</module>
|
||||
<module>driver-examples</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.cassandra</groupId>
|
||||
<artifactId>cassandra-all</artifactId>
|
||||
<version>1.2.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>1.2.17</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>1.6.6</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.10</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.5.1</version>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
<optimize>true</optimize>
|
||||
<showDeprecation>true</showDeprecation>
|
||||
<showWarnings>true</showWarnings>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.9</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache 2</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
<comments>Apache License Version 2.0</comments>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:git@github.com:datastax/java-driver.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:datastax/java-driver.git</developerConnection>
|
||||
<url>https://github.com/datastax/java-driver</url>
|
||||
</scm>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Various</name>
|
||||
<organization>DataStax</organization>
|
||||
</developer>
|
||||
</developers>
|
||||
</project>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<groupId>com.datastax.cassandra</groupId>
|
||||
<artifactId>cassandra-driver-parent</artifactId>
|
||||
<versioning>
|
||||
<release>1.0.0-beta1</release>
|
||||
<versions>
|
||||
<version>1.0.0-beta1</version>
|
||||
</versions>
|
||||
<lastUpdated>20130224090929</lastUpdated>
|
||||
</versioning>
|
||||
</metadata>
|
||||
1
settings.gradle
Normal file
1
settings.gradle
Normal file
@@ -0,0 +1 @@
|
||||
rootProject.name = 'spring-data-cassandra'
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.config;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.cassandra.convert.CassandraConverter;
|
||||
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
|
||||
import org.springframework.data.cassandra.core.CassandraTemplate;
|
||||
import org.springframework.data.cassandra.core.Keyspace;
|
||||
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.cassandra.mapping.Table;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.datastax.driver.core.Cluster;
|
||||
import com.datastax.driver.core.Session;
|
||||
|
||||
/**
|
||||
* Base class for Spring Data Cassandra configuration using JavaConfig.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
@Configuration
|
||||
public abstract class AbstractCassandraConfiguration {
|
||||
|
||||
/**
|
||||
* Return the name of the keyspace to connect to.
|
||||
*
|
||||
* @return must not be {@literal null}.
|
||||
*/
|
||||
protected abstract String getKeyspaceName();
|
||||
|
||||
/**
|
||||
* Return the {@link Cluster} instance to connect to.
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Bean
|
||||
public abstract Cluster cluster() throws Exception;
|
||||
|
||||
/**
|
||||
* Creates a {@link Session} to be used by the {@link Keyspace}. Will use the {@link Cluster} instance
|
||||
* configured in {@link #cluster()}.
|
||||
*
|
||||
* @see #cluster()
|
||||
* @see #Keyspace()
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Bean
|
||||
public Session session() throws Exception {
|
||||
String keyspace = getKeyspaceName();
|
||||
if (StringUtils.hasText(keyspace)) {
|
||||
return cluster().connect(keyspace);
|
||||
}
|
||||
else {
|
||||
return cluster().connect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Keyspace} to be used by the {@link CassandraTemplate}. Will use the {@link Session} instance
|
||||
* configured in {@link #session()} and {@link CassandraConverter} configured in {@link #converter()}.
|
||||
*
|
||||
* @see #cluster()
|
||||
* @see #Keyspace()
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Bean
|
||||
public Keyspace keyspace() throws Exception {
|
||||
return new Keyspace(getKeyspaceName(), session(), converter());
|
||||
}
|
||||
/**
|
||||
* Return the base package to scan for mapped {@link Table}s. Will return the package name of the configuration
|
||||
* class' (the concrete class, not this one here) by default. So if you have a {@code com.acme.AppConfig} extending
|
||||
* {@link AbstractCassandraConfiguration} the base package will be considered {@code com.acme} unless the method is
|
||||
* overriden to implement alternate behaviour.
|
||||
*
|
||||
* @return the base package to scan for mapped {@link Table} classes or {@literal null} to not enable scanning for
|
||||
* entities.
|
||||
*/
|
||||
protected String getMappingBasePackage() {
|
||||
return getClass().getPackage().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link CassandraTemplate}.
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Bean
|
||||
public CassandraTemplate cassandraTemplate() throws Exception {
|
||||
return new CassandraTemplate(keyspace());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link MappingContext} instance to map Entities to properties.
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Bean
|
||||
public MappingContext<? extends CassandraPersistentEntity<?>, CassandraPersistentProperty> mappingContext() {
|
||||
return new CassandraMappingContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link CassandraConverter} instance to convert Rows to Objects.
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Bean
|
||||
public CassandraConverter converter() {
|
||||
return new MappingCassandraConverter(mappingContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans the mapping base package for classes annotated with {@link Table}.
|
||||
*
|
||||
* @see #getMappingBasePackage()
|
||||
* @return
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
|
||||
|
||||
String basePackage = getMappingBasePackage();
|
||||
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
|
||||
|
||||
if (StringUtils.hasText(basePackage)) {
|
||||
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(
|
||||
false);
|
||||
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Table.class));
|
||||
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
|
||||
|
||||
for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {
|
||||
initialEntitySet.add(ClassUtils.forName(candidate.getBeanClassName(),
|
||||
AbstractCassandraConfiguration.class.getClassLoader()));
|
||||
}
|
||||
}
|
||||
|
||||
return initialEntitySet;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.config;
|
||||
|
||||
/**
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class BeanNames {
|
||||
|
||||
static final String CASSANDRA_CLUSTER = "cassandra-cluster";
|
||||
static final String CASSANDRA_KEYSPACE = "cassandra-keyspace";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.config;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.data.cassandra.core.CassandraClusterFactoryBean;
|
||||
import org.springframework.data.config.ParsingUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Parser for <cluster;gt; definitions.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
|
||||
public class CassandraClusterParser extends AbstractSimpleBeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
protected Class<?> getBeanClass(Element element) {
|
||||
return CassandraClusterFactoryBean.class;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#resolveId(org.w3c.dom.Element, org.springframework.beans.factory.support.AbstractBeanDefinition, org.springframework.beans.factory.xml.ParserContext)
|
||||
*/
|
||||
@Override
|
||||
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
|
||||
throws BeanDefinitionStoreException {
|
||||
|
||||
String id = super.resolveId(element, definition, parserContext);
|
||||
return StringUtils.hasText(id) ? id : BeanNames.CASSANDRA_CLUSTER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext,
|
||||
BeanDefinitionBuilder builder) {
|
||||
|
||||
String contactPoints = element.getAttribute("contactPoints");
|
||||
if (StringUtils.hasText(contactPoints)) {
|
||||
builder.addPropertyValue("contactPoints", contactPoints);
|
||||
}
|
||||
|
||||
String port = element.getAttribute("port");
|
||||
if (StringUtils.hasText(port)) {
|
||||
builder.addPropertyValue("port", port);
|
||||
}
|
||||
|
||||
String compression = element.getAttribute("compression");
|
||||
if (StringUtils.hasText(compression)) {
|
||||
builder.addPropertyValue("compressionType", CompressionType.valueOf(compression));
|
||||
}
|
||||
|
||||
postProcess(builder, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postProcess(BeanDefinitionBuilder builder, Element element) {
|
||||
List<Element> subElements = DomUtils.getChildElements(element);
|
||||
|
||||
// parse nested elements
|
||||
for (Element subElement : subElements) {
|
||||
String name = subElement.getLocalName();
|
||||
|
||||
if ("local-pooling-options".equals(name)) {
|
||||
builder.addPropertyValue("localPoolingOptions", parsePoolingOptions(subElement));
|
||||
}
|
||||
else if ("remote-pooling-options".equals(name)) {
|
||||
builder.addPropertyValue("remotePoolingOptions", parsePoolingOptions(subElement));
|
||||
}
|
||||
else if ("socket-options".equals(name)) {
|
||||
builder.addPropertyValue("socketOptions", parseSocketOptions(subElement));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private BeanDefinition parsePoolingOptions(Element element) {
|
||||
BeanDefinitionBuilder defBuilder = BeanDefinitionBuilder.genericBeanDefinition(PoolingOptionsConfig.class);
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "min-simultaneous-requests", "minSimultaneousRequests");
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "max-simultaneous-requests", "maxSimultaneousRequests");
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "core-connections", "coreConnections");
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "max-connections", "maxConnections");
|
||||
return defBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
private BeanDefinition parseSocketOptions(Element element) {
|
||||
BeanDefinitionBuilder defBuilder = BeanDefinitionBuilder.genericBeanDefinition(SocketOptionsConfig.class);
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "connect-timeout-mls", "connectTimeoutMls");
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "keep-alive", "keepAlive");
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "reuse-address", "reuseAddress");
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "so-linger", "soLinger");
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "tcp-no-delay", "tcpNoDelay");
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "receive-buffer-size", "receiveBufferSize");
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "send-buffer-size", "sendBufferSize");
|
||||
return defBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.config;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.data.cassandra.core.CassandraKeyspaceFactoryBean;
|
||||
import org.springframework.data.config.ParsingUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Parser for <keyspace;gt; definitions.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
|
||||
|
||||
public class CassandraKeyspaceParser extends AbstractSimpleBeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
protected Class<?> getBeanClass(Element element) {
|
||||
return CassandraKeyspaceFactoryBean.class;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#resolveId(org.w3c.dom.Element, org.springframework.beans.factory.support.AbstractBeanDefinition, org.springframework.beans.factory.xml.ParserContext)
|
||||
*/
|
||||
@Override
|
||||
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
|
||||
throws BeanDefinitionStoreException {
|
||||
|
||||
String id = super.resolveId(element, definition, parserContext);
|
||||
return StringUtils.hasText(id) ? id : BeanNames.CASSANDRA_KEYSPACE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext,
|
||||
BeanDefinitionBuilder builder) {
|
||||
|
||||
String name = element.getAttribute("name");
|
||||
if (StringUtils.hasText(name)) {
|
||||
builder.addPropertyValue("keyspace", name);
|
||||
}
|
||||
|
||||
String clusterRef = element.getAttribute("cassandra-cluster-ref");
|
||||
if (!StringUtils.hasText(clusterRef)) {
|
||||
clusterRef = BeanNames.CASSANDRA_CLUSTER;
|
||||
}
|
||||
builder.addPropertyReference("cluster", clusterRef);
|
||||
|
||||
String converterRef = element.getAttribute("cassandra-converter-ref");
|
||||
if (StringUtils.hasText(converterRef)) {
|
||||
builder.addPropertyReference("converter", converterRef);
|
||||
}
|
||||
|
||||
postProcess(builder, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postProcess(BeanDefinitionBuilder builder, Element element) {
|
||||
List<Element> subElements = DomUtils.getChildElements(element);
|
||||
|
||||
// parse nested elements
|
||||
for (Element subElement : subElements) {
|
||||
String name = subElement.getLocalName();
|
||||
|
||||
if ("keyspace-attributes".equals(name)) {
|
||||
builder.addPropertyValue("keyspaceAttributes", parseKeyspaceAttributes(subElement));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private BeanDefinition parseKeyspaceAttributes(Element element) {
|
||||
BeanDefinitionBuilder defBuilder = BeanDefinitionBuilder.genericBeanDefinition(KeyspaceAttributes.class);
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "auto", "auto");
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "replication-strategy", "replicationStrategy");
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "replication-factor", "replicationFactor");
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "durable-writes", "durableWrites");
|
||||
|
||||
List<Element> subElements = DomUtils.getChildElements(element);
|
||||
ManagedList<Object> tables = new ManagedList<Object>(subElements.size());
|
||||
|
||||
// parse nested elements
|
||||
for (Element subElement : subElements) {
|
||||
String name = subElement.getLocalName();
|
||||
|
||||
if ("table".equals(name)) {
|
||||
tables.add(parseTable(subElement));
|
||||
}
|
||||
}
|
||||
if (!tables.isEmpty()) {
|
||||
defBuilder.addPropertyValue("tables", tables);
|
||||
}
|
||||
|
||||
return defBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
private BeanDefinition parseTable(Element element) {
|
||||
BeanDefinitionBuilder defBuilder = BeanDefinitionBuilder.genericBeanDefinition(TableAttributes.class);
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "entity", "entity");
|
||||
ParsingUtils.setPropertyValue(defBuilder, element, "name", "name");
|
||||
return defBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.config;
|
||||
|
||||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
|
||||
/**
|
||||
* Namespace handler for <cassandra;gt;.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
|
||||
public class CassandraNamespaceHandler extends NamespaceHandlerSupport {
|
||||
|
||||
public void init() {
|
||||
|
||||
registerBeanDefinitionParser("cluster", new CassandraClusterParser());
|
||||
registerBeanDefinitionParser("keyspace", new CassandraKeyspaceParser());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2010-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.config;
|
||||
|
||||
/**
|
||||
* Simple enumeration for the various compression types.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public enum CompressionType {
|
||||
none, snappy;
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.config;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Keyspace attributes are used for manipulation around keyspace at the startup.
|
||||
* Auto property defines the way how to do this. Other attributes used to
|
||||
* ensure or update keyspace settings.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class KeyspaceAttributes {
|
||||
|
||||
public static final String DEFAULT_REPLICATION_STRATEGY = "SimpleStrategy";
|
||||
public static final int DEFAULT_REPLICATION_FACTOR = 1;
|
||||
public static final boolean DEFAULT_DURABLE_WRITES = true;
|
||||
|
||||
/*
|
||||
* auto possible values:
|
||||
* validate: validate the keyspace, makes no changes.
|
||||
* update: update the keyspace.
|
||||
* create: creates the keyspace, destroying previous data.
|
||||
* create-drop: drop the keyspace at the end of the session.
|
||||
*/
|
||||
public static final String AUTO_VALIDATE = "validate";
|
||||
public static final String AUTO_UPDATE = "update";
|
||||
public static final String AUTO_CREATE = "create";
|
||||
public static final String AUTO_CREATE_DROP = "create-drop";
|
||||
|
||||
private String auto = AUTO_VALIDATE;
|
||||
private String replicationStrategy = DEFAULT_REPLICATION_STRATEGY;
|
||||
private int replicationFactor = DEFAULT_REPLICATION_FACTOR;
|
||||
private boolean durableWrites = DEFAULT_DURABLE_WRITES;
|
||||
|
||||
private Collection<TableAttributes> tables;
|
||||
|
||||
public String getAuto() {
|
||||
return auto;
|
||||
}
|
||||
|
||||
public void setAuto(String auto) {
|
||||
this.auto = auto;
|
||||
}
|
||||
|
||||
public boolean isValidate() {
|
||||
return AUTO_VALIDATE.equals(auto);
|
||||
}
|
||||
|
||||
public boolean isUpdate() {
|
||||
return AUTO_UPDATE.equals(auto);
|
||||
}
|
||||
|
||||
public boolean isCreate() {
|
||||
return AUTO_CREATE.equals(auto);
|
||||
}
|
||||
|
||||
public boolean isCreateDrop() {
|
||||
return AUTO_CREATE_DROP.equals(auto);
|
||||
}
|
||||
|
||||
public String getReplicationStrategy() {
|
||||
return replicationStrategy;
|
||||
}
|
||||
|
||||
public void setReplicationStrategy(String replicationStrategy) {
|
||||
this.replicationStrategy = replicationStrategy;
|
||||
}
|
||||
|
||||
public int getReplicationFactor() {
|
||||
return replicationFactor;
|
||||
}
|
||||
|
||||
public void setReplicationFactor(int replicationFactor) {
|
||||
this.replicationFactor = replicationFactor;
|
||||
}
|
||||
|
||||
public boolean isDurableWrites() {
|
||||
return durableWrites;
|
||||
}
|
||||
|
||||
public void setDurableWrites(boolean durableWrites) {
|
||||
this.durableWrites = durableWrites;
|
||||
}
|
||||
|
||||
public Collection<TableAttributes> getTables() {
|
||||
return tables;
|
||||
}
|
||||
|
||||
public void setTables(Collection<TableAttributes> tables) {
|
||||
this.tables = tables;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.config;
|
||||
|
||||
/**
|
||||
* Pooling options POJO. Can be remote or local.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class PoolingOptionsConfig {
|
||||
|
||||
private Integer minSimultaneousRequests;
|
||||
private Integer maxSimultaneousRequests;
|
||||
private Integer coreConnections;
|
||||
private Integer maxConnections;
|
||||
|
||||
public Integer getMinSimultaneousRequests() {
|
||||
return minSimultaneousRequests;
|
||||
}
|
||||
|
||||
public void setMinSimultaneousRequests(Integer minSimultaneousRequests) {
|
||||
this.minSimultaneousRequests = minSimultaneousRequests;
|
||||
}
|
||||
|
||||
public Integer getMaxSimultaneousRequests() {
|
||||
return maxSimultaneousRequests;
|
||||
}
|
||||
|
||||
public void setMaxSimultaneousRequests(Integer maxSimultaneousRequests) {
|
||||
this.maxSimultaneousRequests = maxSimultaneousRequests;
|
||||
}
|
||||
|
||||
public Integer getCoreConnections() {
|
||||
return coreConnections;
|
||||
}
|
||||
|
||||
public void setCoreConnections(Integer coreConnections) {
|
||||
this.coreConnections = coreConnections;
|
||||
}
|
||||
|
||||
public Integer getMaxConnections() {
|
||||
return maxConnections;
|
||||
}
|
||||
|
||||
public void setMaxConnections(Integer maxConnections) {
|
||||
this.maxConnections = maxConnections;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.config;
|
||||
|
||||
/**
|
||||
* Socket options POJO. Uses to configure Netty.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class SocketOptionsConfig {
|
||||
|
||||
private Integer connectTimeoutMls;
|
||||
private Boolean keepAlive;
|
||||
private Boolean reuseAddress;
|
||||
private Integer soLinger;
|
||||
private Boolean tcpNoDelay;
|
||||
private Integer receiveBufferSize;
|
||||
private Integer sendBufferSize;
|
||||
|
||||
public Integer getConnectTimeoutMls() {
|
||||
return connectTimeoutMls;
|
||||
}
|
||||
|
||||
public void setConnectTimeoutMls(Integer connectTimeoutMls) {
|
||||
this.connectTimeoutMls = connectTimeoutMls;
|
||||
}
|
||||
|
||||
public Boolean getKeepAlive() {
|
||||
return keepAlive;
|
||||
}
|
||||
|
||||
public void setKeepAlive(Boolean keepAlive) {
|
||||
this.keepAlive = keepAlive;
|
||||
}
|
||||
|
||||
public Boolean getReuseAddress() {
|
||||
return reuseAddress;
|
||||
}
|
||||
|
||||
public void setReuseAddress(Boolean reuseAddress) {
|
||||
this.reuseAddress = reuseAddress;
|
||||
}
|
||||
|
||||
public Integer getSoLinger() {
|
||||
return soLinger;
|
||||
}
|
||||
|
||||
public void setSoLinger(Integer soLinger) {
|
||||
this.soLinger = soLinger;
|
||||
}
|
||||
|
||||
public Boolean getTcpNoDelay() {
|
||||
return tcpNoDelay;
|
||||
}
|
||||
|
||||
public void setTcpNoDelay(Boolean tcpNoDelay) {
|
||||
this.tcpNoDelay = tcpNoDelay;
|
||||
}
|
||||
|
||||
public Integer getReceiveBufferSize() {
|
||||
return receiveBufferSize;
|
||||
}
|
||||
|
||||
public void setReceiveBufferSize(Integer receiveBufferSize) {
|
||||
this.receiveBufferSize = receiveBufferSize;
|
||||
}
|
||||
|
||||
public Integer getSendBufferSize() {
|
||||
return sendBufferSize;
|
||||
}
|
||||
|
||||
public void setSendBufferSize(Integer sendBufferSize) {
|
||||
this.sendBufferSize = sendBufferSize;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.config;
|
||||
|
||||
/**
|
||||
* Table attributes are used for manipulation around table at the startup (create/update/validate).
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class TableAttributes {
|
||||
|
||||
private String entity;
|
||||
private String name;
|
||||
|
||||
public String getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
public void setEntity(String entity) {
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TableAttributes [entity=" + entity + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.convert;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.convert.EntityInstantiators;
|
||||
|
||||
/**
|
||||
* Base class for {@link CassandraConverter} implementations. Sets up a {@link GenericConversionService} and populates basic
|
||||
* converters.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public abstract class AbstractCassandraConverter implements CassandraConverter, InitializingBean {
|
||||
|
||||
protected final GenericConversionService conversionService;
|
||||
protected EntityInstantiators instantiators = new EntityInstantiators();
|
||||
|
||||
/**
|
||||
* Creates a new {@link AbstractMongoConverter} using the given {@link GenericConversionService}.
|
||||
*
|
||||
* @param conversionService
|
||||
*/
|
||||
public AbstractCassandraConverter(GenericConversionService conversionService) {
|
||||
this.conversionService = conversionService == null ? new DefaultConversionService() : conversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers {@link EntityInstantiators} to customize entity instantiation.
|
||||
*
|
||||
* @param instantiators
|
||||
*/
|
||||
public void setInstantiators(EntityInstantiators instantiators) {
|
||||
this.instantiators = instantiators == null ? new EntityInstantiators() : instantiators;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.core.convert.MongoConverter#getConversionService()
|
||||
*/
|
||||
public ConversionService getConversionService() {
|
||||
return conversionService;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.convert;
|
||||
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.convert.EntityConverter;
|
||||
|
||||
import com.datastax.driver.core.Row;
|
||||
|
||||
/**
|
||||
* Central Cassandra specific converter interface from Object to Row.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public interface CassandraConverter extends EntityConverter<CassandraPersistentEntity<?>, CassandraPersistentProperty, Object, Row> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.convert;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator;
|
||||
import org.springframework.data.mapping.model.PropertyValueProvider;
|
||||
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
import com.datastax.driver.core.Row;
|
||||
|
||||
/**
|
||||
* {@link PropertyValueProvider} to read property values from a {@link Row}.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class CassandraPropertyValueProvider implements PropertyValueProvider<CassandraPersistentProperty> {
|
||||
|
||||
private final Row source;
|
||||
private final SpELExpressionEvaluator evaluator;
|
||||
|
||||
/**
|
||||
* Creates a new {@link CassandraPropertyValueProvider} with the given {@link Row} and {@link DefaultSpELExpressionEvaluator}.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @param evaluator must not be {@literal null}.
|
||||
*/
|
||||
public CassandraPropertyValueProvider(Row source, DefaultSpELExpressionEvaluator evaluator) {
|
||||
Assert.notNull(source);
|
||||
Assert.notNull(evaluator);
|
||||
|
||||
this.source = source;
|
||||
this.evaluator = evaluator;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.convert.PropertyValueProvider#getPropertyValue(org.springframework.data.mapping.PersistentProperty)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getPropertyValue(CassandraPersistentProperty property) {
|
||||
|
||||
String expression = property.getSpelExpression();
|
||||
if (expression != null) {
|
||||
return evaluator.evaluate(expression);
|
||||
}
|
||||
|
||||
String columnName = property.getColumnName();
|
||||
if (source.isNull(property.getColumnName())) {
|
||||
return null;
|
||||
}
|
||||
DataType columnType = source.getColumnDefinitions().getType(columnName);
|
||||
ByteBuffer bytes = source.getBytes(columnName);
|
||||
return (T) columnType.deserialize(bytes);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright 2011-2013 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.convert;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.convert.EntityInstantiator;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.BeanWrapper;
|
||||
import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.model.PersistentEntityParameterValueProvider;
|
||||
import org.springframework.data.mapping.model.PropertyValueProvider;
|
||||
import org.springframework.data.mapping.model.SpELContext;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
import com.datastax.driver.core.Row;
|
||||
|
||||
/**
|
||||
* {@link CassandraConverter} that uses a {@link MappingContext} to do sophisticated mapping of domain objects to
|
||||
* {@link Row}.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class MappingCassandraConverter extends AbstractCassandraConverter implements ApplicationContextAware {
|
||||
|
||||
protected static final Logger log = LoggerFactory.getLogger(MappingCassandraConverter.class);
|
||||
|
||||
protected final MappingContext<? extends CassandraPersistentEntity<?>, CassandraPersistentProperty> mappingContext;
|
||||
protected ApplicationContext applicationContext;
|
||||
private SpELContext spELContext;
|
||||
private boolean useFieldAccessOnly = true;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MappingCassandraConverter} given the new {@link MappingContext}.
|
||||
*
|
||||
* @param mappingContext must not be {@literal null}.
|
||||
*/
|
||||
public MappingCassandraConverter(MappingContext<? extends CassandraPersistentEntity<?>, CassandraPersistentProperty> mappingContext) {
|
||||
super(new DefaultConversionService());
|
||||
this.mappingContext = mappingContext;
|
||||
this.spELContext = new SpELContext(RowReaderPropertyAccessor.INSTANCE);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <R> R read(Class<R> clazz, Row row) {
|
||||
|
||||
TypeInformation<? extends R> type = ClassTypeInformation.from(clazz);
|
||||
//TypeInformation<? extends R> typeToUse = typeMapper.readType(row, type);
|
||||
TypeInformation<? extends R> typeToUse = type;
|
||||
Class<? extends R> rawType = typeToUse.getType();
|
||||
|
||||
if (Row.class.isAssignableFrom(rawType)) {
|
||||
return (R) row;
|
||||
}
|
||||
|
||||
CassandraPersistentEntity<R> persistentEntity = (CassandraPersistentEntity<R>) mappingContext.getPersistentEntity(typeToUse);
|
||||
if (persistentEntity == null) {
|
||||
throw new MappingException("No mapping metadata found for " + rawType.getName());
|
||||
}
|
||||
|
||||
return read(persistentEntity, row);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.convert.EntityConverter#getMappingContext()
|
||||
*/
|
||||
public MappingContext<? extends CassandraPersistentEntity<?>, CassandraPersistentProperty> getMappingContext() {
|
||||
return mappingContext;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||
*/
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
this.spELContext = new SpELContext(this.spELContext, applicationContext);
|
||||
}
|
||||
|
||||
private <S extends Object> S read(final CassandraPersistentEntity<S> entity, final Row row) {
|
||||
|
||||
final DefaultSpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(row, spELContext);
|
||||
|
||||
final PropertyValueProvider<CassandraPersistentProperty> propertyProvider = new CassandraPropertyValueProvider(row, evaluator);
|
||||
PersistentEntityParameterValueProvider<CassandraPersistentProperty> parameterProvider = new PersistentEntityParameterValueProvider<CassandraPersistentProperty>(
|
||||
entity, propertyProvider, null);
|
||||
|
||||
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
|
||||
S instance = instantiator.createInstance(entity, parameterProvider);
|
||||
|
||||
final BeanWrapper<CassandraPersistentEntity<S>, S> wrapper = BeanWrapper.create(instance, conversionService);
|
||||
final S result = wrapper.getBean();
|
||||
|
||||
// Set properties not already set in the constructor
|
||||
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
|
||||
|
||||
boolean isConstructorProperty = entity.isConstructorArgument(prop);
|
||||
boolean hasValueForProperty = row.getColumnDefinitions().contains(prop.getColumnName());
|
||||
|
||||
if (!hasValueForProperty || isConstructorProperty) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object obj = propertyProvider.getPropertyValue(prop);
|
||||
wrapper.setProperty(prop, obj, useFieldAccessOnly);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void write(Object source, Row sink) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void setUseFieldAccessOnly(boolean useFieldAccessOnly) {
|
||||
this.useFieldAccessOnly = useFieldAccessOnly;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.convert;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.PropertyAccessor;
|
||||
import org.springframework.expression.TypedValue;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
import com.datastax.driver.core.Row;
|
||||
|
||||
/**
|
||||
* {@link PropertyAccessor} to read values from a {@link Row}.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
enum RowReaderPropertyAccessor implements PropertyAccessor {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.expression.PropertyAccessor#getSpecificTargetClasses()
|
||||
*/
|
||||
public Class<?>[] getSpecificTargetClasses() {
|
||||
return new Class<?>[] { Row.class };
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.expression.PropertyAccessor#canRead(org.springframework.expression.EvaluationContext, java.lang.Object, java.lang.String)
|
||||
*/
|
||||
public boolean canRead(EvaluationContext context, Object target, String name) {
|
||||
return ((Row) target).getColumnDefinitions().contains(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.expression.PropertyAccessor#read(org.springframework.expression.EvaluationContext, java.lang.Object, java.lang.String)
|
||||
*/
|
||||
public TypedValue read(EvaluationContext context, Object target, String name) {
|
||||
Row row = (Row) target;
|
||||
if (row.isNull(name)) {
|
||||
return TypedValue.NULL;
|
||||
}
|
||||
DataType columnType = row.getColumnDefinitions().getType(name);
|
||||
ByteBuffer bytes = row.getBytes(name);
|
||||
Object object = columnType.deserialize(bytes);
|
||||
return new TypedValue(object);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.expression.PropertyAccessor#canWrite(org.springframework.expression.EvaluationContext, java.lang.Object, java.lang.String)
|
||||
*/
|
||||
public boolean canWrite(EvaluationContext context, Object target, String name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.expression.PropertyAccessor#write(org.springframework.expression.EvaluationContext, java.lang.Object, java.lang.String, java.lang.Object)
|
||||
*/
|
||||
public void write(EvaluationContext context, Object target, String name, Object newValue) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.core;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.cassandra.config.CompressionType;
|
||||
import org.springframework.data.cassandra.config.PoolingOptionsConfig;
|
||||
import org.springframework.data.cassandra.config.SocketOptionsConfig;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.datastax.driver.core.AuthProvider;
|
||||
import com.datastax.driver.core.Cluster;
|
||||
import com.datastax.driver.core.HostDistance;
|
||||
import com.datastax.driver.core.PoolingOptions;
|
||||
import com.datastax.driver.core.ProtocolOptions.Compression;
|
||||
import com.datastax.driver.core.SocketOptions;
|
||||
import com.datastax.driver.core.policies.LoadBalancingPolicy;
|
||||
import com.datastax.driver.core.policies.ReconnectionPolicy;
|
||||
import com.datastax.driver.core.policies.RetryPolicy;
|
||||
|
||||
/**
|
||||
* Convenient factory for configuring a Cassandra Cluster.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
|
||||
public class CassandraClusterFactoryBean implements FactoryBean<Cluster>,
|
||||
InitializingBean, DisposableBean, PersistenceExceptionTranslator {
|
||||
|
||||
private static final int DEFAULT_PORT = 9042;
|
||||
|
||||
private Cluster cluster;
|
||||
|
||||
private String contactPoints;
|
||||
private int port = DEFAULT_PORT;
|
||||
private CompressionType compressionType;
|
||||
|
||||
private PoolingOptionsConfig localPoolingOptions;
|
||||
private PoolingOptionsConfig remotePoolingOptions;
|
||||
private SocketOptionsConfig socketOptions;
|
||||
|
||||
private AuthProvider authProvider;
|
||||
private LoadBalancingPolicy loadBalancingPolicy;
|
||||
private ReconnectionPolicy reconnectionPolicy;
|
||||
private RetryPolicy retryPolicy;
|
||||
|
||||
private boolean metricsEnabled = true;
|
||||
|
||||
private final PersistenceExceptionTranslator exceptionTranslator = new CassandraExceptionTranslator();
|
||||
|
||||
public Cluster getObject() throws Exception {
|
||||
return cluster;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
|
||||
*/
|
||||
public Class<? extends Cluster> getObjectType() {
|
||||
return Cluster.class;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.FactoryBean#isSingleton()
|
||||
*/
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException)
|
||||
*/
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
return exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
|
||||
if (!StringUtils.hasText(contactPoints)) {
|
||||
throw new IllegalArgumentException(
|
||||
"at least one server is required");
|
||||
}
|
||||
|
||||
Cluster.Builder builder = Cluster.builder();
|
||||
|
||||
builder.addContactPoints(StringUtils.commaDelimitedListToStringArray(contactPoints)).withPort(port);
|
||||
|
||||
if (compressionType != null) {
|
||||
builder.withCompression(convertCompressionType(compressionType));
|
||||
}
|
||||
|
||||
if (localPoolingOptions != null) {
|
||||
builder.withPoolingOptions(configPoolingOptions(HostDistance.LOCAL, localPoolingOptions));
|
||||
}
|
||||
|
||||
if (remotePoolingOptions != null) {
|
||||
builder.withPoolingOptions(configPoolingOptions(HostDistance.REMOTE, remotePoolingOptions));
|
||||
}
|
||||
|
||||
if (socketOptions != null) {
|
||||
builder.withSocketOptions(configSocketOptions(socketOptions));
|
||||
}
|
||||
|
||||
if (authProvider != null) {
|
||||
builder.withAuthProvider(authProvider);
|
||||
}
|
||||
|
||||
if (loadBalancingPolicy != null) {
|
||||
builder.withLoadBalancingPolicy(loadBalancingPolicy);
|
||||
}
|
||||
|
||||
if (reconnectionPolicy != null) {
|
||||
builder.withReconnectionPolicy(reconnectionPolicy);
|
||||
}
|
||||
|
||||
if (retryPolicy != null) {
|
||||
builder.withRetryPolicy(retryPolicy);
|
||||
}
|
||||
|
||||
if (!metricsEnabled) {
|
||||
builder.withoutMetrics();
|
||||
}
|
||||
|
||||
Cluster cluster = builder.build();
|
||||
|
||||
// initialize property
|
||||
this.cluster = cluster;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.DisposableBean#destroy()
|
||||
*/
|
||||
public void destroy() throws Exception {
|
||||
this.cluster.shutdown();
|
||||
}
|
||||
|
||||
public void setContactPoints(String contactPoints) {
|
||||
this.contactPoints = contactPoints;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void setCompressionType(CompressionType compressionType) {
|
||||
this.compressionType = compressionType;
|
||||
}
|
||||
|
||||
public void setLocalPoolingOptions(PoolingOptionsConfig localPoolingOptions) {
|
||||
this.localPoolingOptions = localPoolingOptions;
|
||||
}
|
||||
|
||||
public void setRemotePoolingOptions(PoolingOptionsConfig remotePoolingOptions) {
|
||||
this.remotePoolingOptions = remotePoolingOptions;
|
||||
}
|
||||
|
||||
public void setSocketOptions(SocketOptionsConfig socketOptions) {
|
||||
this.socketOptions = socketOptions;
|
||||
}
|
||||
|
||||
public void setAuthProvider(AuthProvider authProvider) {
|
||||
this.authProvider = authProvider;
|
||||
}
|
||||
|
||||
public void setLoadBalancingPolicy(LoadBalancingPolicy loadBalancingPolicy) {
|
||||
this.loadBalancingPolicy = loadBalancingPolicy;
|
||||
}
|
||||
|
||||
public void setReconnectionPolicy(ReconnectionPolicy reconnectionPolicy) {
|
||||
this.reconnectionPolicy = reconnectionPolicy;
|
||||
}
|
||||
|
||||
public void setRetryPolicy(RetryPolicy retryPolicy) {
|
||||
this.retryPolicy = retryPolicy;
|
||||
}
|
||||
|
||||
public void setMetricsEnabled(boolean metricsEnabled) {
|
||||
this.metricsEnabled = metricsEnabled;
|
||||
}
|
||||
|
||||
private static Compression convertCompressionType(CompressionType type) {
|
||||
switch(type) {
|
||||
case none:
|
||||
return Compression.NONE;
|
||||
case snappy:
|
||||
return Compression.SNAPPY;
|
||||
}
|
||||
throw new IllegalArgumentException("unknown compression type " + type);
|
||||
}
|
||||
|
||||
private static PoolingOptions configPoolingOptions(HostDistance hostDistance, PoolingOptionsConfig config) {
|
||||
PoolingOptions poolingOptions = new PoolingOptions();
|
||||
|
||||
if (config.getMinSimultaneousRequests() != null) {
|
||||
poolingOptions.setMinSimultaneousRequestsPerConnectionThreshold(hostDistance, config.getMinSimultaneousRequests());
|
||||
}
|
||||
if (config.getMaxSimultaneousRequests() != null) {
|
||||
poolingOptions.setMaxSimultaneousRequestsPerConnectionThreshold(hostDistance, config.getMaxSimultaneousRequests());
|
||||
}
|
||||
if (config.getCoreConnections() != null) {
|
||||
poolingOptions.setCoreConnectionsPerHost(hostDistance, config.getCoreConnections());
|
||||
}
|
||||
if (config.getMaxConnections() != null) {
|
||||
poolingOptions.setMaxConnectionsPerHost(hostDistance, config.getMaxConnections());
|
||||
}
|
||||
|
||||
return poolingOptions;
|
||||
}
|
||||
|
||||
private static SocketOptions configSocketOptions(SocketOptionsConfig config) {
|
||||
SocketOptions socketOptions = new SocketOptions();
|
||||
|
||||
if (config.getConnectTimeoutMls() != null) {
|
||||
socketOptions.setConnectTimeoutMillis(config.getConnectTimeoutMls());
|
||||
}
|
||||
if (config.getKeepAlive() != null) {
|
||||
socketOptions.setKeepAlive(config.getKeepAlive());
|
||||
}
|
||||
if (config.getReuseAddress() != null) {
|
||||
socketOptions.setReuseAddress(config.getReuseAddress());
|
||||
}
|
||||
if (config.getSoLinger() != null) {
|
||||
socketOptions.setSoLinger(config.getSoLinger());
|
||||
}
|
||||
if (config.getTcpNoDelay() != null) {
|
||||
socketOptions.setTcpNoDelay(config.getTcpNoDelay());
|
||||
}
|
||||
if (config.getReceiveBufferSize() != null) {
|
||||
socketOptions.setReceiveBufferSize(config.getReceiveBufferSize());
|
||||
}
|
||||
if (config.getSendBufferSize() != null) {
|
||||
socketOptions.setSendBufferSize(config.getSendBufferSize());
|
||||
}
|
||||
|
||||
return socketOptions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.core;
|
||||
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
|
||||
/**
|
||||
* Cassandra connection exception.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class CassandraConnectionFailureException extends DataAccessResourceFailureException {
|
||||
|
||||
public CassandraConnectionFailureException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public CassandraConnectionFailureException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.core;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
|
||||
import com.datastax.driver.core.exceptions.InvalidQueryException;
|
||||
|
||||
/**
|
||||
* Simple {@link PersistenceExceptionTranslator} for Cassandra. Convert the given runtime exception to an appropriate
|
||||
* exception from the {@code org.springframework.dao} hierarchy. Return {@literal null} if no translation is
|
||||
* appropriate: any other exception may have resulted from user code, and should not be translated.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
|
||||
public class CassandraExceptionTranslator implements PersistenceExceptionTranslator {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException)
|
||||
*/
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
|
||||
// Check for well-known Cassandra subclasses.
|
||||
|
||||
if (ex instanceof InvalidQueryException) {
|
||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
// If we get here, we have an exception that resulted from user code,
|
||||
// rather than the persistence provider, so we return null to indicate
|
||||
// that translation should not occur.
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.core;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.cassandra.config.KeyspaceAttributes;
|
||||
import org.springframework.data.cassandra.config.TableAttributes;
|
||||
import org.springframework.data.cassandra.convert.CassandraConverter;
|
||||
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
|
||||
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.cassandra.util.CQLUtils;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.datastax.driver.core.Cluster;
|
||||
import com.datastax.driver.core.KeyspaceMetadata;
|
||||
import com.datastax.driver.core.Session;
|
||||
import com.datastax.driver.core.TableMetadata;
|
||||
import com.datastax.driver.core.exceptions.NoHostAvailableException;
|
||||
|
||||
/**
|
||||
* Convenient factory for configuring a Cassandra Session.
|
||||
* Session is a thread safe singleton and created per a keyspace.
|
||||
* So, it is enough to have one session per application.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
|
||||
public class CassandraKeyspaceFactoryBean implements FactoryBean<Keyspace>,
|
||||
InitializingBean, DisposableBean, BeanClassLoaderAware, PersistenceExceptionTranslator {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(CassandraKeyspaceFactoryBean.class);
|
||||
|
||||
public static final String DEFAULT_REPLICATION_STRATEGY = "SimpleStrategy";
|
||||
public static final int DEFAULT_REPLICATION_FACTOR = 1;
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
private Cluster cluster;
|
||||
private Session session;
|
||||
private String keyspace;
|
||||
|
||||
private CassandraConverter converter;
|
||||
private MappingContext<? extends CassandraPersistentEntity<?>, CassandraPersistentProperty> mappingContext;
|
||||
|
||||
private Keyspace keyspaceBean;
|
||||
|
||||
private KeyspaceAttributes keyspaceAttributes;
|
||||
|
||||
private final PersistenceExceptionTranslator exceptionTranslator = new CassandraExceptionTranslator();
|
||||
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
}
|
||||
|
||||
|
||||
public Keyspace getObject() throws Exception {
|
||||
return keyspaceBean;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
|
||||
*/
|
||||
public Class<? extends Session> getObjectType() {
|
||||
return Session.class;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.FactoryBean#isSingleton()
|
||||
*/
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException)
|
||||
*/
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
return exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
|
||||
if (this.converter == null) {
|
||||
this.converter = getDefaultCassandraConverter();
|
||||
}
|
||||
this.mappingContext = this.converter.getMappingContext();
|
||||
|
||||
|
||||
if (cluster == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"at least one cluster is required");
|
||||
}
|
||||
|
||||
Session session = null;
|
||||
session = cluster.connect();
|
||||
|
||||
if (StringUtils.hasText(keyspace)) {
|
||||
|
||||
KeyspaceMetadata keyspaceMetadata = cluster.getMetadata().getKeyspace(keyspace.toLowerCase());
|
||||
boolean keyspaceExists = keyspaceMetadata != null;
|
||||
boolean keyspaceCreated = false;
|
||||
|
||||
if (keyspaceExists) {
|
||||
log.info("keyspace exists " + keyspaceMetadata.asCQLQuery());
|
||||
}
|
||||
|
||||
if (keyspaceAttributes == null) {
|
||||
keyspaceAttributes = new KeyspaceAttributes();
|
||||
}
|
||||
|
||||
// drop the old keyspace if needed
|
||||
if (keyspaceExists && (keyspaceAttributes.isCreate() || keyspaceAttributes.isCreateDrop())) {
|
||||
log.info("Drop keyspace " + keyspace + " on afterPropertiesSet");
|
||||
session.execute("DROP KEYSPACE " + keyspace);
|
||||
keyspaceExists = false;
|
||||
}
|
||||
|
||||
// create the new keyspace if needed
|
||||
if (!keyspaceExists && (keyspaceAttributes.isCreate() || keyspaceAttributes.isCreateDrop() || keyspaceAttributes.isUpdate())) {
|
||||
|
||||
String query = String.format("CREATE KEYSPACE %1$s WITH replication = { 'class' : '%2$s', 'replication_factor' : %3$d } AND DURABLE_WRITES = %4$b",
|
||||
keyspace,
|
||||
keyspaceAttributes.getReplicationStrategy(),
|
||||
keyspaceAttributes.getReplicationFactor(),
|
||||
keyspaceAttributes.isDurableWrites());
|
||||
|
||||
log.info("Create keyspace " + keyspace + " on afterPropertiesSet " + query);
|
||||
|
||||
session.execute(query);
|
||||
keyspaceCreated = true;
|
||||
}
|
||||
|
||||
// update keyspace if needed
|
||||
if (keyspaceAttributes.isUpdate() && !keyspaceCreated) {
|
||||
|
||||
if (compareKeyspaceAttributes(keyspaceAttributes, keyspaceMetadata) != null) {
|
||||
|
||||
String query = String.format("ALTER KEYSPACE %1$s WITH replication = { 'class' : '%2$s', 'replication_factor' : %3$d } AND DURABLE_WRITES = %4$b",
|
||||
keyspace,
|
||||
keyspaceAttributes.getReplicationStrategy(),
|
||||
keyspaceAttributes.getReplicationFactor(),
|
||||
keyspaceAttributes.isDurableWrites());
|
||||
|
||||
log.info("Update keyspace " + keyspace + " on afterPropertiesSet " + query);
|
||||
session.execute(query);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// validate keyspace if needed
|
||||
if (keyspaceAttributes.isValidate()) {
|
||||
|
||||
if (!keyspaceExists) {
|
||||
throw new InvalidDataAccessApiUsageException("keyspace '" + keyspace + "' not found in the Cassandra");
|
||||
}
|
||||
|
||||
String errorField = compareKeyspaceAttributes(keyspaceAttributes, keyspaceMetadata);
|
||||
if (errorField != null) {
|
||||
throw new InvalidDataAccessApiUsageException(errorField + " attribute is not much in the keyspace '" + keyspace + "'");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
session.execute("USE " + keyspace);
|
||||
|
||||
if (!CollectionUtils.isEmpty(keyspaceAttributes.getTables())) {
|
||||
|
||||
for (TableAttributes tableAttributes : keyspaceAttributes.getTables()) {
|
||||
|
||||
String entityClassName = tableAttributes.getEntity();
|
||||
Class<?> entityClass = ClassUtils.forName(entityClassName, this.beanClassLoader);
|
||||
CassandraPersistentEntity<?> entity = determineEntity(entityClass);
|
||||
String useTableName = tableAttributes.getName() != null ? tableAttributes.getName() : entity.getTable();
|
||||
|
||||
if (keyspaceCreated) {
|
||||
createNewTable(session, useTableName, entity);
|
||||
}
|
||||
else if (keyspaceAttributes.isUpdate()) {
|
||||
TableMetadata table = keyspaceMetadata.getTable(useTableName.toLowerCase());
|
||||
if (table == null) {
|
||||
createNewTable(session, useTableName, entity);
|
||||
}
|
||||
else {
|
||||
// alter table columns
|
||||
for (String cql : CQLUtils.alterTable(useTableName, entity, table)) {
|
||||
log.info("Execute on keyspace " + keyspace + " CQL " + cql);
|
||||
session.execute(cql);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (keyspaceAttributes.isValidate()) {
|
||||
TableMetadata table = keyspaceMetadata.getTable(useTableName.toLowerCase());
|
||||
if (table == null) {
|
||||
throw new InvalidDataAccessApiUsageException("not found table " + useTableName + " for entity " + entityClassName);
|
||||
}
|
||||
// validate columns
|
||||
List<String> alter = CQLUtils.alterTable(useTableName, entity, table);
|
||||
if (!alter.isEmpty()) {
|
||||
throw new InvalidDataAccessApiUsageException("invalid table " + useTableName + " for entity " + entityClassName + ". modify it by " + alter);
|
||||
}
|
||||
}
|
||||
|
||||
//System.out.println("tableAttributes, entityClass=" + entityClass + ", table = " + entity.getTable());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// initialize property
|
||||
this.session = session;
|
||||
|
||||
this.keyspaceBean = new Keyspace(keyspace, session, converter);
|
||||
}
|
||||
|
||||
|
||||
private void createNewTable(Session session, String useTableName,
|
||||
CassandraPersistentEntity<?> entity)
|
||||
throws NoHostAvailableException {
|
||||
String cql = CQLUtils.createTable(useTableName, entity);
|
||||
log.info("Execute on keyspace " + keyspace + " CQL " + cql);
|
||||
session.execute(cql);
|
||||
for (String indexCQL : CQLUtils.createIndexes(useTableName, entity)) {
|
||||
log.info("Execute on keyspace " + keyspace + " CQL " + indexCQL);
|
||||
session.execute(indexCQL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.DisposableBean#destroy()
|
||||
*/
|
||||
public void destroy() throws Exception {
|
||||
|
||||
if (StringUtils.hasText(keyspace) && keyspaceAttributes != null && keyspaceAttributes.isCreateDrop()) {
|
||||
log.info("Drop keyspace " + keyspace + " on destroy");
|
||||
session.execute("USE system");
|
||||
session.execute("DROP KEYSPACE " + keyspace);
|
||||
}
|
||||
this.session.shutdown();
|
||||
}
|
||||
|
||||
public void setKeyspace(String keyspace) {
|
||||
this.keyspace = keyspace;
|
||||
}
|
||||
|
||||
public void setCluster(Cluster cluster) {
|
||||
this.cluster = cluster;
|
||||
}
|
||||
|
||||
public void setKeyspaceAttributes(KeyspaceAttributes keyspaceAttributes) {
|
||||
this.keyspaceAttributes = keyspaceAttributes;
|
||||
}
|
||||
|
||||
public void setConverter(CassandraConverter converter) {
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
private static String compareKeyspaceAttributes(KeyspaceAttributes keyspaceAttributes, KeyspaceMetadata keyspaceMetadata) {
|
||||
if (keyspaceAttributes.isDurableWrites() != keyspaceMetadata.isDurableWrites()) {
|
||||
return "durableWrites";
|
||||
}
|
||||
Map<String, String> replication = keyspaceMetadata.getReplication();
|
||||
String replicationFactorStr = replication.get("replication_factor");
|
||||
if (replicationFactorStr == null) {
|
||||
return "replication_factor";
|
||||
}
|
||||
try {
|
||||
int replicationFactor = Integer.parseInt(replicationFactorStr);
|
||||
if (keyspaceAttributes.getReplicationFactor() != replicationFactor) {
|
||||
return "replication_factor";
|
||||
}
|
||||
}
|
||||
catch(NumberFormatException e) {
|
||||
return "replication_factor";
|
||||
}
|
||||
|
||||
String attributesStrategy = keyspaceAttributes.getReplicationStrategy();
|
||||
if (attributesStrategy.indexOf('.') == -1) {
|
||||
attributesStrategy = "org.apache.cassandra.locator." + attributesStrategy;
|
||||
}
|
||||
String replicationStrategy = replication.get("class");
|
||||
if (!attributesStrategy.equals(replicationStrategy)) {
|
||||
return "replication_class";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
CassandraPersistentEntity<?> determineEntity(Class<?> entityClass) {
|
||||
|
||||
if (entityClass == null) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"No class parameter provided, entity table name can't be determined!");
|
||||
}
|
||||
|
||||
CassandraPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
if (entity == null) {
|
||||
throw new InvalidDataAccessApiUsageException("No Persitent Entity information found for the class "
|
||||
+ entityClass.getName());
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
private static final CassandraConverter getDefaultCassandraConverter() {
|
||||
MappingCassandraConverter converter = new MappingCassandraConverter(new CassandraMappingContext());
|
||||
converter.afterPropertiesSet();
|
||||
return converter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.cassandra.convert.CassandraConverter;
|
||||
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
import com.datastax.driver.core.querybuilder.Update;
|
||||
|
||||
/**
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public interface CassandraOperations {
|
||||
|
||||
/**
|
||||
* The table name used for the specified class by this template.
|
||||
*
|
||||
* @param entityClass must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
String getTableName(Class<?> entityClass);
|
||||
|
||||
/**
|
||||
* Execute query and return Cassandra ResultSet
|
||||
*
|
||||
* @param query must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
ResultSet executeQuery(String query);
|
||||
|
||||
/**
|
||||
* Execute query and convert ResultSet to the list of entities
|
||||
*
|
||||
* @param query must not be {@literal null}.
|
||||
* @param selectClass must not be {@literal null}, mapped entity type.
|
||||
* @return
|
||||
*/
|
||||
<T> List<T> select(String query, Class<T> selectClass);
|
||||
|
||||
/**
|
||||
* Execute query and convert ResultSet to the entity
|
||||
*
|
||||
* @param query must not be {@literal null}.
|
||||
* @param selectClass must not be {@literal null}, mapped entity type.
|
||||
* @return
|
||||
*/
|
||||
<T> T selectOne(String query, Class<T> selectClass);
|
||||
|
||||
/**
|
||||
* Insert the given object to the table by id.
|
||||
*
|
||||
* @param object
|
||||
*/
|
||||
void insert(Object entity);
|
||||
|
||||
/**
|
||||
* Insert the given object to the table by id.
|
||||
*
|
||||
* @param object
|
||||
*/
|
||||
void insert(Object entity, String tableName);
|
||||
|
||||
/**
|
||||
* Remove the given object from the table by id.
|
||||
*
|
||||
* @param object
|
||||
*/
|
||||
void remove(Object object);
|
||||
|
||||
/**
|
||||
* Removes the given object from the given table.
|
||||
*
|
||||
* @param object
|
||||
* @param table must not be {@literal null} or empty.
|
||||
*/
|
||||
void remove(Object object, String tableName);
|
||||
|
||||
/**
|
||||
* Create a table with the name and fields indicated by the entity class
|
||||
*
|
||||
* @param entityClass class that determines metadata of the table to create/drop.
|
||||
*/
|
||||
void createTable(Class<?> entityClass);
|
||||
|
||||
/**
|
||||
* Create a table with the name and fields indicated by the entity class
|
||||
*
|
||||
* @param entityClass class that determines metadata of the table to create/drop.
|
||||
* @param tableName explicit name of the table
|
||||
*/
|
||||
void createTable(Class<?> entityClass, String tableName);
|
||||
|
||||
/**
|
||||
* Alter table with the name and fields indicated by the entity class
|
||||
*
|
||||
* @param entityClass class that determines metadata of the table to create/drop.
|
||||
*/
|
||||
void alterTable(Class<?> entityClass);
|
||||
|
||||
/**
|
||||
* Alter table with the name and fields indicated by the entity class
|
||||
*
|
||||
* @param entityClass class that determines metadata of the table to create/drop.
|
||||
* @param tableName explicit name of the table
|
||||
*/
|
||||
void alterTable(Class<?> entityClass, String tableName);
|
||||
|
||||
/**
|
||||
* Alter table with the name and fields indicated by the entity class
|
||||
*
|
||||
* @param entityClass class that determines metadata of the table to create/drop.
|
||||
*/
|
||||
void dropTable(Class<?> entityClass);
|
||||
|
||||
/**
|
||||
* Alter table with the name and fields indicated by the entity class
|
||||
*
|
||||
* @param tableName explicit name of the table.
|
||||
*/
|
||||
void dropTable(String tableName);
|
||||
|
||||
/**
|
||||
* Returns the underlying {@link CassandraConverter}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
CassandraConverter getConverter();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.core;
|
||||
|
||||
import org.springframework.dao.UncategorizedDataAccessException;
|
||||
|
||||
/**
|
||||
* Exception thrown when we can't classify a Cassandra exception into one of Spring generic data access exceptions.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
|
||||
public class CassandraSystemException extends UncategorizedDataAccessException {
|
||||
|
||||
public CassandraSystemException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.cassandra.convert.CassandraConverter;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.convert.EntityReader;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
import com.datastax.driver.core.Row;
|
||||
import com.datastax.driver.core.Session;
|
||||
import com.datastax.driver.core.exceptions.NoHostAvailableException;
|
||||
|
||||
/**
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class CassandraTemplate implements CassandraOperations {
|
||||
|
||||
private final Session session;
|
||||
private final CassandraConverter cassandraConverter;
|
||||
private final MappingContext<? extends CassandraPersistentEntity<?>, CassandraPersistentProperty> mappingContext;
|
||||
|
||||
private final PersistenceExceptionTranslator exceptionTranslator = new CassandraExceptionTranslator();
|
||||
|
||||
/**
|
||||
* Constructor used for a basic template configuration
|
||||
*
|
||||
* @param keyspace must not be {@literal null}.
|
||||
*/
|
||||
public CassandraTemplate(Keyspace keyspace) {
|
||||
this.session = keyspace.getSession();
|
||||
this.cassandraConverter = keyspace.getCassandraConverter();
|
||||
this.mappingContext = this.cassandraConverter.getMappingContext();
|
||||
}
|
||||
|
||||
public String getTableName(Class<?> entityClass) {
|
||||
return determineTableName(entityClass);
|
||||
}
|
||||
|
||||
public ResultSet executeQuery(String query) {
|
||||
try {
|
||||
return session.execute(query);
|
||||
} catch (NoHostAvailableException e) {
|
||||
throw new CassandraConnectionFailureException("no host available", e);
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> List<T> select(String query, Class<T> selectClass) {
|
||||
return selectInternal(query, new ReadRowCallback<T>(cassandraConverter, selectClass));
|
||||
}
|
||||
|
||||
public <T> T selectOne(String query, Class<T> selectClass) {
|
||||
return selectOneInternal(query, new ReadRowCallback<T>(cassandraConverter, selectClass));
|
||||
}
|
||||
|
||||
|
||||
public void insert(Object entity) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void insert(Object entity, String tableName) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void remove(Object object) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void remove(Object object, String tableName) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void createTable(Class<?> entityClass) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void createTable(Class<?> entityClass, String tableName) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void alterTable(Class<?> entityClass) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void alterTable(Class<?> entityClass, String tableName) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void dropTable(Class<?> entityClass) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void dropTable(String tableName) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public CassandraConverter getConverter() {
|
||||
return cassandraConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple internal callback to allow operations on a {@link Row}.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
|
||||
private interface RowCallback<T> {
|
||||
|
||||
T doWith(Row object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple {@link RowCallback} that will transform {@link Row} into the given target type using the given
|
||||
* {@link EntityReader}.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
private static class ReadRowCallback<T> implements RowCallback<T> {
|
||||
|
||||
private final EntityReader<? super T, Row> reader;
|
||||
private final Class<T> type;
|
||||
|
||||
public ReadRowCallback(EntityReader<? super T, Row> reader, Class<T> type) {
|
||||
Assert.notNull(reader);
|
||||
Assert.notNull(type);
|
||||
this.reader = reader;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public T doWith(Row object) {
|
||||
T source = reader.read(type, object);
|
||||
return source;
|
||||
}
|
||||
}
|
||||
|
||||
<T> List<T> selectInternal(String query, ReadRowCallback<T> readRowCallback) {
|
||||
try {
|
||||
ResultSet resultSet = session.execute(query);
|
||||
List<T> result = new ArrayList<T>();
|
||||
Iterator<Row> iterator = resultSet.iterator();
|
||||
while(iterator.hasNext()) {
|
||||
Row row = iterator.next();
|
||||
result.add(readRowCallback.doWith(row));
|
||||
}
|
||||
return result;
|
||||
} catch (NoHostAvailableException e) {
|
||||
throw new CassandraConnectionFailureException("no host available", e);
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
<T> T selectOneInternal(String query, ReadRowCallback<T> readRowCallback) {
|
||||
try {
|
||||
ResultSet resultSet = session.execute(query);
|
||||
Iterator<Row> iterator = resultSet.iterator();
|
||||
if (iterator.hasNext()) {
|
||||
Row row = iterator.next();
|
||||
T result = readRowCallback.doWith(row);
|
||||
if (iterator.hasNext()) {
|
||||
throw new DuplicateKeyException("found two or more results in query " + query);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
} catch (NoHostAvailableException e) {
|
||||
throw new CassandraConnectionFailureException("no host available", e);
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
String determineTableName(Class<?> entityClass) {
|
||||
|
||||
if (entityClass == null) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"No class parameter provided, entity table name can't be determined!");
|
||||
}
|
||||
|
||||
CassandraPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
if (entity == null) {
|
||||
throw new InvalidDataAccessApiUsageException("No Persitent Entity information found for the class "
|
||||
+ entityClass.getName());
|
||||
}
|
||||
return entity.getTable();
|
||||
}
|
||||
|
||||
private RuntimeException potentiallyConvertRuntimeException(
|
||||
RuntimeException ex) {
|
||||
RuntimeException resolved = this.exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
return resolved == null ? ex : resolved;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.core;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
|
||||
/**
|
||||
* Simple Cassandra value of the ByteBuffer with DataType
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class CassandraValue {
|
||||
|
||||
private final ByteBuffer value;
|
||||
private final DataType type;
|
||||
|
||||
public CassandraValue(ByteBuffer value, DataType type) {
|
||||
this.value = value;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public ByteBuffer getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public DataType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.core;
|
||||
|
||||
import org.springframework.data.cassandra.convert.CassandraConverter;
|
||||
|
||||
import com.datastax.driver.core.Session;
|
||||
|
||||
/**
|
||||
* Simple Cassandra Keyspace object
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class Keyspace {
|
||||
|
||||
private final String keyspace;
|
||||
private final Session session;
|
||||
private final CassandraConverter cassandraConverter;
|
||||
|
||||
/**
|
||||
* Constructor used for a basic keyspace configuration
|
||||
*
|
||||
* @param keyspace, system if {@literal null}.
|
||||
* @param session must not be {@literal null}.
|
||||
* @param cassandraConverter must not be {@literal null}.
|
||||
*/
|
||||
public Keyspace(String keyspace, Session session, CassandraConverter cassandraConverter) {
|
||||
this.keyspace = keyspace;
|
||||
this.session = session;
|
||||
this.cassandraConverter = cassandraConverter;
|
||||
}
|
||||
|
||||
public String getKeyspace() {
|
||||
return keyspace;
|
||||
}
|
||||
|
||||
public Session getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
public CassandraConverter getCassandraConverter() {
|
||||
return cassandraConverter;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.springframework.data.cassandra.cql;
|
||||
|
||||
public abstract class CQLBuilder {
|
||||
|
||||
public static CreateTable createTable(String tableName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.springframework.data.cassandra.cql;
|
||||
|
||||
public class CreateTable {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.mapping;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.expression.BeanFactoryAccessor;
|
||||
import org.springframework.context.expression.BeanFactoryResolver;
|
||||
import org.springframework.data.cassandra.util.CassandraNamingUtils;
|
||||
import org.springframework.data.mapping.model.BasicPersistentEntity;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ParserContext;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Cassandra specific {@link BasicPersistentEntity} implementation that adds Cassandra specific meta-data such as the
|
||||
* table name.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T, CassandraPersistentProperty> implements
|
||||
CassandraPersistentEntity<T>, ApplicationContextAware {
|
||||
|
||||
private final String table;
|
||||
private final SpelExpressionParser parser;
|
||||
private final StandardEvaluationContext context;
|
||||
|
||||
/**
|
||||
* Creates a new {@link BasicCassandraPersistentEntity} with the given {@link TypeInformation}. Will default the
|
||||
* table name to the entities simple type name.
|
||||
*
|
||||
* @param typeInformation
|
||||
*/
|
||||
public BasicCassandraPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
|
||||
super(typeInformation, CassandraPersistentPropertyComparator.INSTANCE);
|
||||
|
||||
this.parser = new SpelExpressionParser();
|
||||
this.context = new StandardEvaluationContext();
|
||||
|
||||
Class<?> rawType = typeInformation.getType();
|
||||
String fallback = CassandraNamingUtils.getPreferredTableName(rawType);
|
||||
|
||||
if (rawType.isAnnotationPresent(Table.class)) {
|
||||
Table d = rawType.getAnnotation(Table.class);
|
||||
this.table = StringUtils.hasText(d.name()) ? d.name() : fallback;
|
||||
} else {
|
||||
this.table = fallback;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||
*/
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
|
||||
context.addPropertyAccessor(new BeanFactoryAccessor());
|
||||
context.setBeanResolver(new BeanFactoryResolver(applicationContext));
|
||||
context.setRootObject(applicationContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the table the entity shall be persisted to.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getTable() {
|
||||
Expression expression = parser.parseExpression(table, ParserContext.TEMPLATE_EXPRESSION);
|
||||
return expression.getValue(context, String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Comparator} implementation inspecting the {@link CassandraPersistentProperty}'s order.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
static enum CassandraPersistentPropertyComparator implements Comparator<CassandraPersistentProperty> {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
public int compare(CassandraPersistentProperty o1, CassandraPersistentProperty o2) {
|
||||
|
||||
if (o1.isColumnId()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (o2.isColumnId()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return o1.getColumnName().compareTo(o2.getColumnName());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.mapping;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
|
||||
/**
|
||||
* Cassandra specific {@link org.springframework.data.mapping.model.AnnotationBasedPersistentProperty} implementation.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentProperty<CassandraPersistentProperty> implements
|
||||
CassandraPersistentProperty {
|
||||
|
||||
/**
|
||||
* Creates a new {@link BasicCassandraPersistentProperty}.
|
||||
*
|
||||
* @param field
|
||||
* @param propertyDescriptor
|
||||
* @param owner
|
||||
* @param simpleTypeHolder
|
||||
*/
|
||||
public BasicCassandraPersistentProperty(Field field, PropertyDescriptor propertyDescriptor,
|
||||
CassandraPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||
super(field, propertyDescriptor, owner, simpleTypeHolder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Also considers fields that has a RowId annotation.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public boolean isIdProperty() {
|
||||
|
||||
if (super.isIdProperty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return getField().isAnnotationPresent(RowId.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* For dynamic tables returns true if property value is used as column name.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isColumnId() {
|
||||
return getField().isAnnotationPresent(ColumnId.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the column name to be used to store the value of the property inside the Cassandra.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getColumnName() {
|
||||
Column annotation = getField().getAnnotation(Column.class);
|
||||
return annotation != null && StringUtils.hasText(annotation.value()) ? annotation.value() : field.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data type information if exists.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public DataType getDataType() {
|
||||
Qualify annotation = getField().getAnnotation(Qualify.class);
|
||||
if (annotation != null && annotation.type() != null) {
|
||||
return qualifyAnnotatedType(annotation);
|
||||
}
|
||||
if (isMap()) {
|
||||
List<TypeInformation<?>> args = getTypeInformation().getTypeArguments();
|
||||
ensureTypeArguments(args.size(), 2);
|
||||
return DataType.map(autodetectPrimitiveType(args.get(0).getType()), autodetectPrimitiveType(args.get(1).getType()));
|
||||
}
|
||||
if (isCollectionLike()) {
|
||||
List<TypeInformation<?>> args = getTypeInformation().getTypeArguments();
|
||||
ensureTypeArguments(args.size(), 1);
|
||||
if (Set.class.isAssignableFrom(getType())) {
|
||||
return DataType.set(autodetectPrimitiveType(args.get(0).getType()));
|
||||
}
|
||||
else if (List.class.isAssignableFrom(getType())) {
|
||||
return DataType.list(autodetectPrimitiveType(args.get(0).getType()));
|
||||
}
|
||||
}
|
||||
DataType dataType = CassandraSimpleTypes.autodetectPrimitive(this.getType());
|
||||
if (dataType == null) {
|
||||
throw new InvalidDataAccessApiUsageException("only primitive types and Set,List,Map collections are allowed, unknown type for property '" + this.getName() + "' type is '" + this.getType() + "' in the entity " + this.getOwner().getName());
|
||||
}
|
||||
return dataType;
|
||||
}
|
||||
|
||||
private DataType qualifyAnnotatedType(Qualify annotation) {
|
||||
DataType.Name type = annotation.type();
|
||||
if (type.isCollection()) {
|
||||
switch(type) {
|
||||
case MAP:
|
||||
ensureTypeArguments(annotation.typeArguments().length, 2);
|
||||
return DataType.map(resolvePrimitiveType(annotation.typeArguments()[0]),
|
||||
resolvePrimitiveType(annotation.typeArguments()[1]));
|
||||
case LIST:
|
||||
ensureTypeArguments(annotation.typeArguments().length, 1);
|
||||
return DataType.list(resolvePrimitiveType(annotation.typeArguments()[0]));
|
||||
case SET:
|
||||
ensureTypeArguments(annotation.typeArguments().length, 1);
|
||||
return DataType.set(resolvePrimitiveType(annotation.typeArguments()[0]));
|
||||
default:
|
||||
throw new InvalidDataAccessApiUsageException("unknown collection DataType for property '" + this.getName() + "' type is '" + this.getType() + "' in the entity " + this.getOwner().getName());
|
||||
}
|
||||
}
|
||||
else {
|
||||
return CassandraSimpleTypes.resolvePrimitive(type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the property has secondary index on this column.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isIndexed() {
|
||||
return getField().isAnnotationPresent(Index.class);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.model.AbstractPersistentProperty#createAssociation()
|
||||
*/
|
||||
@Override
|
||||
protected Association<CassandraPersistentProperty> createAssociation() {
|
||||
return new Association<CassandraPersistentProperty>(this, null);
|
||||
}
|
||||
|
||||
DataType resolvePrimitiveType(DataType.Name typeName) {
|
||||
DataType dataType = CassandraSimpleTypes.resolvePrimitive(typeName);
|
||||
if (dataType == null) {
|
||||
throw new InvalidDataAccessApiUsageException("only primitive types are allowed inside collections for the property '" + this.getName() + "' type is '" + this.getType() + "' in the entity " + this.getOwner().getName());
|
||||
}
|
||||
return dataType;
|
||||
}
|
||||
|
||||
DataType autodetectPrimitiveType(Class<?> javaType) {
|
||||
DataType dataType = CassandraSimpleTypes.autodetectPrimitive(javaType);
|
||||
if (dataType == null) {
|
||||
throw new InvalidDataAccessApiUsageException("only primitive types are allowed inside collections for the property '" + this.getName() + "' type is '" + this.getType() + "' in the entity " + this.getOwner().getName());
|
||||
}
|
||||
return dataType;
|
||||
}
|
||||
|
||||
void ensureTypeArguments(int args, int expected) {
|
||||
if (args != expected) {
|
||||
throw new InvalidDataAccessApiUsageException("expected " + expected + " of typed arguments for the property '" + this.getName() + "' type is '" + this.getType() + "' in the entity " + this.getOwner().getName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.mapping;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
|
||||
|
||||
/**
|
||||
* {@link CassandraPersistentProperty} caching access to {@link #isIdProperty()} and {@link #getColumnName()}.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class CachingCassandraPersistentProperty extends BasicCassandraPersistentProperty {
|
||||
|
||||
private Boolean isIdProperty;
|
||||
private Boolean isColumnId;
|
||||
private String columnName;
|
||||
private Boolean isIndexed;
|
||||
|
||||
/**
|
||||
* Creates a new {@link CachingCassandraPersistentProperty}.
|
||||
*
|
||||
* @param field
|
||||
* @param propertyDescriptor
|
||||
* @param owner
|
||||
* @param simpleTypeHolder
|
||||
*/
|
||||
public CachingCassandraPersistentProperty(Field field, PropertyDescriptor propertyDescriptor,
|
||||
CassandraPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||
super(field, propertyDescriptor, owner, simpleTypeHolder);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.BasicCassandraPersistentProperty#isIdProperty()
|
||||
*/
|
||||
@Override
|
||||
public boolean isIdProperty() {
|
||||
|
||||
if (this.isIdProperty == null) {
|
||||
this.isIdProperty = super.isIdProperty();
|
||||
}
|
||||
|
||||
return this.isIdProperty;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.BasicCassandraPersistentProperty#isColumnId()
|
||||
*/
|
||||
@Override
|
||||
public boolean isColumnId() {
|
||||
|
||||
if (this.isColumnId == null) {
|
||||
this.isColumnId = super.isColumnId();
|
||||
}
|
||||
|
||||
return this.isColumnId;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.BasicCassandraPersistentProperty#getFieldName()
|
||||
*/
|
||||
@Override
|
||||
public String getColumnName() {
|
||||
|
||||
if (this.columnName == null) {
|
||||
this.columnName = super.getColumnName();
|
||||
}
|
||||
|
||||
return this.columnName;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.BasicCassandraPersistentProperty#isIndexed()
|
||||
*/
|
||||
@Override
|
||||
public boolean isIndexed() {
|
||||
|
||||
if (this.isIndexed == null) {
|
||||
this.isIndexed = super.isIndexed();
|
||||
}
|
||||
|
||||
return this.isIndexed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.mapping;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.data.mapping.context.AbstractMappingContext;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
/**
|
||||
* Default implementation of a {@link MappingContext} for Cassandra using {@link BasicCassandraPersistentEntity} and
|
||||
* {@link BasicCassandraPersistentProperty} as primary abstractions.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class CassandraMappingContext extends AbstractMappingContext<BasicCassandraPersistentEntity<?>, CassandraPersistentProperty>
|
||||
implements ApplicationContextAware {
|
||||
|
||||
private ApplicationContext context;
|
||||
|
||||
/**
|
||||
* Creates a new {@link CassandraMappingContext}.
|
||||
*/
|
||||
public CassandraMappingContext() {
|
||||
setSimpleTypeHolder(CassandraSimpleTypes.HOLDER);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.AbstractMappingContext#createPersistentProperty(java.lang.reflect.Field, java.beans.PropertyDescriptor, org.springframework.data.mapping.MutablePersistentEntity, org.springframework.data.mapping.SimpleTypeHolder)
|
||||
*/
|
||||
@Override
|
||||
public CassandraPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
|
||||
BasicCassandraPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||
return new CachingCassandraPersistentProperty(field, descriptor, owner, simpleTypeHolder);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.BasicMappingContext#createPersistentEntity(org.springframework.data.util.TypeInformation, org.springframework.data.mapping.model.MappingContext)
|
||||
*/
|
||||
@Override
|
||||
protected <T> BasicCassandraPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
|
||||
BasicCassandraPersistentEntity<T> entity = new BasicCassandraPersistentEntity<T>(typeInformation);
|
||||
|
||||
if (context != null) {
|
||||
entity.setApplicationContext(context);
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||
*/
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
|
||||
this.context = applicationContext;
|
||||
super.setApplicationContext(applicationContext);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.mapping;
|
||||
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
|
||||
/**
|
||||
* Cassandra specific {@link PersistentEntity} abstraction.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public interface CassandraPersistentEntity<T> extends PersistentEntity<T, CassandraPersistentProperty> {
|
||||
|
||||
/**
|
||||
* Returns the table the entity shall be persisted to.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getTable();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.mapping;
|
||||
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
|
||||
/**
|
||||
* Cassandra specific {@link org.springframework.data.mapping.PersistentProperty} extension.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public interface CassandraPersistentProperty extends PersistentProperty<CassandraPersistentProperty> {
|
||||
|
||||
/**
|
||||
* For dynamic tables returns true if property value is used as column name.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isColumnId();
|
||||
|
||||
/**
|
||||
* Returns the name of the field a property is persisted to.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getColumnName();
|
||||
|
||||
/**
|
||||
* Returns the data type.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
DataType getDataType();
|
||||
|
||||
/**
|
||||
* Returns true if the property has secondary index on this column.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isIndexed();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.mapping;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
|
||||
/**
|
||||
* Simple constant holder for a {@link SimpleTypeHolder} enriched with Cassandra specific simple types.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class CassandraSimpleTypes {
|
||||
|
||||
private static final Map<Class<?>, Class<?>> primitiveWrapperTypeMap = new HashMap<Class<?>, Class<?>>(8);
|
||||
|
||||
private static final Map<Class<?>, DataType> javaClassToDataType = new HashMap<Class<?>, DataType>();
|
||||
|
||||
private static final Map<DataType.Name, DataType> nameToDataType = new HashMap<DataType.Name, DataType>();
|
||||
|
||||
static {
|
||||
|
||||
primitiveWrapperTypeMap.put(Boolean.class, boolean.class);
|
||||
primitiveWrapperTypeMap.put(Byte.class, byte.class);
|
||||
primitiveWrapperTypeMap.put(Character.class, char.class);
|
||||
primitiveWrapperTypeMap.put(Double.class, double.class);
|
||||
primitiveWrapperTypeMap.put(Float.class, float.class);
|
||||
primitiveWrapperTypeMap.put(Integer.class, int.class);
|
||||
primitiveWrapperTypeMap.put(Long.class, long.class);
|
||||
primitiveWrapperTypeMap.put(Short.class, short.class);
|
||||
|
||||
Set<Class<?>> simpleTypes = new HashSet<Class<?>>();
|
||||
for (DataType dataType : DataType.allPrimitiveTypes()) {
|
||||
simpleTypes.add(dataType.asJavaClass());
|
||||
Class<?> javaClass = dataType.asJavaClass();
|
||||
javaClassToDataType.put(javaClass, dataType);
|
||||
Class<?> primitiveJavaClass = primitiveWrapperTypeMap.get(javaClass);
|
||||
if (primitiveJavaClass != null) {
|
||||
javaClassToDataType.put(primitiveJavaClass, dataType);
|
||||
}
|
||||
nameToDataType.put(dataType.getName(), dataType);
|
||||
}
|
||||
javaClassToDataType.put(String.class, DataType.text());
|
||||
CASSANDRA_SIMPLE_TYPES = Collections.unmodifiableSet(simpleTypes);
|
||||
}
|
||||
|
||||
private static final Set<Class<?>> CASSANDRA_SIMPLE_TYPES;
|
||||
public static final SimpleTypeHolder HOLDER = new SimpleTypeHolder(CASSANDRA_SIMPLE_TYPES, true);
|
||||
|
||||
private CassandraSimpleTypes() {
|
||||
}
|
||||
|
||||
public static DataType resolvePrimitive(DataType.Name name) {
|
||||
return nameToDataType.get(name);
|
||||
}
|
||||
|
||||
public static DataType autodetectPrimitive(Class<?> javaClass) {
|
||||
return javaClassToDataType.get(javaClass);
|
||||
}
|
||||
|
||||
public static DataType.Name[] convertPrimitiveTypeArguments(List<TypeInformation<?>> arguments) {
|
||||
DataType.Name[] result = new DataType.Name[arguments.size()];
|
||||
for (int i = 0; i != result.length; ++i) {
|
||||
TypeInformation<?> type = arguments.get(i);
|
||||
DataType dataType = autodetectPrimitive(type.getType());
|
||||
if (dataType == null) {
|
||||
throw new InvalidDataAccessApiUsageException("not found appropriate primitive DataType for type = '" + type.getType());
|
||||
}
|
||||
result[i] = dataType.getName();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.springframework.data.cassandra.mapping;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Annotation to define custom metadata for document fields.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Column {
|
||||
|
||||
/**
|
||||
* The name of the column in the table.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.mapping;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Uses in dynamic tables where column names are values of this field.
|
||||
* Usually it is a Date/Time field or UUIDTime field.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
@Retention(value=RetentionPolicy.RUNTIME)
|
||||
@Target(value={ElementType.FIELD,ElementType.METHOD,ElementType.ANNOTATION_TYPE})
|
||||
public @interface ColumnId {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.mapping;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
|
||||
/**
|
||||
* Uses to transfer DataType and attributes for the property.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class DataTypeInformation {
|
||||
|
||||
public static DataType.Name[] EMPTY_ATTRIBUTES = {};
|
||||
|
||||
private DataType.Name typeName;
|
||||
private DataType.Name[] typeAttributes;
|
||||
|
||||
public DataTypeInformation(DataType.Name typeName) {
|
||||
this(typeName, EMPTY_ATTRIBUTES);
|
||||
}
|
||||
|
||||
public DataTypeInformation(DataType.Name typeName, DataType.Name[] typeAttributes) {
|
||||
this.typeName = typeName;
|
||||
this.typeAttributes = typeAttributes;
|
||||
}
|
||||
|
||||
public DataType.Name getTypeName() {
|
||||
return typeName;
|
||||
}
|
||||
|
||||
public void setTypeName(DataType.Name typeName) {
|
||||
this.typeName = typeName;
|
||||
}
|
||||
|
||||
public DataType.Name[] getTypeAttributes() {
|
||||
return typeAttributes;
|
||||
}
|
||||
|
||||
public void setTypeAttributes(DataType.Name[] typeAttributes) {
|
||||
this.typeAttributes = typeAttributes;
|
||||
}
|
||||
|
||||
public String toCQL() {
|
||||
if (typeAttributes.length == 0) {
|
||||
return typeName.name();
|
||||
}
|
||||
else {
|
||||
StringBuilder str = new StringBuilder();
|
||||
str.append(typeName.name());
|
||||
str.append('<');
|
||||
for (int i = 0; i != typeAttributes.length; ++i) {
|
||||
if (i != 0) {
|
||||
str.append(',');
|
||||
}
|
||||
str.append(typeAttributes[i].name());
|
||||
}
|
||||
str.append('>');
|
||||
return str.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.mapping;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Identifies a secondary index in the table. Usually it is a field with common dublicate values
|
||||
* for the hole table. such as city, place, educationType, state flags ant etc.
|
||||
*
|
||||
* Using unique fields is not common and has overhead, such as email, username and etc.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
@Retention(value=RetentionPolicy.RUNTIME)
|
||||
@Target(value={ElementType.FIELD,ElementType.METHOD,ElementType.ANNOTATION_TYPE})
|
||||
public @interface Index {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.mapping;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
|
||||
/**
|
||||
* Qualifies data type as Cassandra type.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Qualify {
|
||||
|
||||
DataType.Name type();
|
||||
|
||||
DataType.Name[] typeArguments() default {};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.mapping;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
/**
|
||||
* Identifies row ID in the Cassandra table. Same as @org.springframework.data.annotation.Id
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
@Retention(value=RetentionPolicy.RUNTIME)
|
||||
@Target(value={ElementType.FIELD,ElementType.METHOD,ElementType.ANNOTATION_TYPE})
|
||||
@Id
|
||||
public @interface RowId {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.mapping;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
|
||||
/**
|
||||
* Identifies a domain object to be persisted to Cassandra as a table.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
@Persistent
|
||||
@Inherited
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.TYPE })
|
||||
public @interface Table {
|
||||
|
||||
String name() default "";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package org.springframework.data.cassandra.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
|
||||
import com.datastax.driver.core.ColumnMetadata;
|
||||
import com.datastax.driver.core.DataType;
|
||||
import com.datastax.driver.core.TableMetadata;
|
||||
|
||||
|
||||
public abstract class CQLUtils {
|
||||
|
||||
public static String createTable(String tableName, final CassandraPersistentEntity<?> entity) {
|
||||
|
||||
final StringBuilder str = new StringBuilder();
|
||||
str.append("CREATE TABLE ");
|
||||
str.append(tableName);
|
||||
str.append('(');
|
||||
|
||||
final List<String> ids = new ArrayList<String>();
|
||||
final List<String> idColumns = new ArrayList<String>();
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
|
||||
|
||||
if (str.charAt(str.length()-1) != '(') {
|
||||
str.append(',');
|
||||
}
|
||||
|
||||
String columnName = prop.getColumnName();
|
||||
|
||||
str.append(columnName);
|
||||
str.append(' ');
|
||||
|
||||
DataType dataType = prop.getDataType();
|
||||
|
||||
str.append(toCQL(dataType));
|
||||
|
||||
if (prop.isIdProperty()) {
|
||||
ids.add(prop.getColumnName());
|
||||
}
|
||||
|
||||
if (prop.isColumnId()) {
|
||||
idColumns.add(prop.getColumnName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
if (ids.isEmpty()) {
|
||||
throw new InvalidDataAccessApiUsageException("not found primary ID in the entity " + entity.getType());
|
||||
}
|
||||
|
||||
str.append(",PRIMARY KEY(");
|
||||
|
||||
if (ids.size() > 1) {
|
||||
str.append('(');
|
||||
}
|
||||
|
||||
for (String id: ids) {
|
||||
if (str.charAt(str.length()-1) != '(') {
|
||||
str.append(',');
|
||||
}
|
||||
str.append(id);
|
||||
}
|
||||
|
||||
if (ids.size() > 1) {
|
||||
str.append(')');
|
||||
}
|
||||
|
||||
for (String id: idColumns) {
|
||||
str.append(',');
|
||||
str.append(id);
|
||||
}
|
||||
|
||||
str.append("));");
|
||||
|
||||
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
public static List<String> createIndexes(final String tableName, final CassandraPersistentEntity<?> entity) {
|
||||
final List<String> result = new ArrayList<String>();
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
|
||||
|
||||
if (prop.isIndexed()) {
|
||||
|
||||
final StringBuilder str = new StringBuilder();
|
||||
str.append("CREATE INDEX ON ");
|
||||
str.append(tableName);
|
||||
str.append(" (");
|
||||
str.append(prop.getColumnName());
|
||||
str.append(");");
|
||||
|
||||
result.add(str.toString());
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<String> alterTable(final String tableName, final CassandraPersistentEntity<?> entity, final TableMetadata table) {
|
||||
final List<String> result = new ArrayList<String>();
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
|
||||
|
||||
String columnName = prop.getColumnName();
|
||||
DataType columnDataType = prop.getDataType();
|
||||
ColumnMetadata columnMetadata = table.getColumn(columnName.toLowerCase());
|
||||
|
||||
if (columnMetadata != null && columnDataType.equals(columnMetadata.getType())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final StringBuilder str = new StringBuilder();
|
||||
str.append("ALTER TABLE ");
|
||||
str.append(tableName);
|
||||
if (columnMetadata == null) {
|
||||
str.append(" ADD ");
|
||||
}
|
||||
else {
|
||||
str.append(" ALTER ");
|
||||
}
|
||||
|
||||
str.append(columnName);
|
||||
str.append(' ');
|
||||
|
||||
if (columnMetadata != null) {
|
||||
str.append("TYPE ");
|
||||
}
|
||||
|
||||
str.append(toCQL(columnDataType));
|
||||
|
||||
str.append(';');
|
||||
result.add(str.toString());
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//System.out.println("CQL=" + table.asCQLQuery());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String toCQL(DataType dataType) {
|
||||
if (dataType.getTypeArguments().isEmpty()) {
|
||||
return dataType.getName().name();
|
||||
}
|
||||
else {
|
||||
StringBuilder str = new StringBuilder();
|
||||
str.append(dataType.getName().name());
|
||||
str.append('<');
|
||||
for (DataType argDataType : dataType.getTypeArguments()) {
|
||||
if (str.charAt(str.length()-1) != '<') {
|
||||
str.append(',');
|
||||
}
|
||||
str.append(argDataType.getName().name());
|
||||
}
|
||||
str.append('>');
|
||||
return str.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.util;
|
||||
|
||||
|
||||
/**
|
||||
* Helper class featuring helper methods for working with Cassandra tables.
|
||||
* Mainly intended for internal use within the framework.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public abstract class CassandraNamingUtils {
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation.
|
||||
*/
|
||||
private CassandraNamingUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the table name to use for the provided class
|
||||
*
|
||||
* @param entityClass The class to determine the preferred table name for
|
||||
* @return The preferred collection name
|
||||
*/
|
||||
public static String getPreferredTableName(Class<?> entityClass) {
|
||||
return entityClass.getSimpleName().toLowerCase();
|
||||
}
|
||||
|
||||
}
|
||||
1
src/main/resources/META-INF/spring.handlers
Normal file
1
src/main/resources/META-INF/spring.handlers
Normal file
@@ -0,0 +1 @@
|
||||
http\://www.springframework.org/schema/data/cassandra=org.springframework.data.cassandra.config.CassandraNamespaceHandler
|
||||
2
src/main/resources/META-INF/spring.schemas
Normal file
2
src/main/resources/META-INF/spring.schemas
Normal file
@@ -0,0 +1,2 @@
|
||||
http\://www.springframework.org/schema/data/cassandra/spring-cassandra-1.0.xsd=org/springframework/data/cassandra/config/spring-cassandra-1.0.xsd
|
||||
http\://www.springframework.org/schema/data/cassandra/spring-cassandra.xsd=org/springframework/data/cassandra/config/spring-cassandra-1.0.xsd
|
||||
4
src/main/resources/META-INF/spring.tooling
Normal file
4
src/main/resources/META-INF/spring.tooling
Normal file
@@ -0,0 +1,4 @@
|
||||
# Tooling related information for the jms namespace
|
||||
http\://www.springframework.org/schema/data/cassnadra@name=Cassandra Namespace
|
||||
http\://www.springframework.org/schema/data/cassandra@prefix=cassandra
|
||||
http\://www.springframework.org/schema/data/cassnadra@icon=org/springframework/data/cassandra/config/spring-cassandra.gif
|
||||
@@ -0,0 +1,404 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<xsd:schema xmlns="http://www.springframework.org/schema/data/cassandra"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
targetNamespace="http://www.springframework.org/schema/data/cassandra"
|
||||
elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
|
||||
<xsd:import namespace="http://www.springframework.org/schema/tool"
|
||||
schemaLocation="http://www.springframework.org/schema/tool/spring-tool.xsd" />
|
||||
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines the configuration elements for the Spring Data Cassandra support.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
<xsd:element name="cluster" type="clusterType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation
|
||||
source="org.springframework.data.cassandra.core.CassandraClusterFactoryBean"><![CDATA[
|
||||
Defines a Cassandra Cluster instance used for accessing Cassandra'.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
<tool:exports type="com.datastax.driver.core.Cluster" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:complexType name="clusterType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="local-pooling-options"
|
||||
type="poolingOptionsType" maxOccurs="1" minOccurs="0">
|
||||
</xsd:element>
|
||||
<xsd:element name="remote-pooling-options"
|
||||
type="poolingOptionsType" maxOccurs="1" minOccurs="0">
|
||||
</xsd:element>
|
||||
<xsd:element name="socket-options" type="socketOptionsType" maxOccurs="1" minOccurs="0"></xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="id" type="xsd:ID" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The name of the Cassandra Cluster definition (by
|
||||
default "cassandra-cluster")
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="contactPoints" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The comma separated hosts to Cassandra servers. Default is localhost
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="port" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The port to connect to Cassandra server as native CQL client. Default is 9042
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="compression" default="none"
|
||||
use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The protocol options compression. Default is 'none'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="none">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
No compression.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:enumeration>
|
||||
<xsd:enumeration value="snappy">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Uses SNAPPY compression algorithm.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:enumeration>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="auth-info-provider" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
AuthInfoProvider implementation.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to type="com.datastax.driver.core.AuthInfoProvider" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string" />
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="load-balancing-policy" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
LoadBalancingPolicy implementation.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to type="com.datastax.driver.core.policies.LoadBalancingPolicy" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string" />
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="reconnection-policy" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
ReconnectionPolicy implementation.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to type="com.datastax.driver.core.policies.ReconnectionPolicy" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string" />
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="retry-policy" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
RetryPolicy implementation.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to type="com.datastax.driver.core.policies.RetryPolicy" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string" />
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="keyspace" type="keyspaceType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.data.cassandra.core.CassandraKeyspaceFactoryBean"><![CDATA[
|
||||
Defines a Cassandra Session instance used for accessing Cassandra Keyspace'.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
<tool:exports type="com.datastax.driver.core.Session" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:complexType name="keyspaceType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="keyspace-attributes" type="keyspaceAttributesType" maxOccurs="1" minOccurs="0"></xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="id" type="xsd:ID" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The name of the Keyspace definition (by default
|
||||
"cassandra-keyspace")
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="name" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The keyspace name of the Cassandra database.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="cassandra-cluster-ref" type="clusterRef"
|
||||
use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The reference to a Cassandra Cluster instance. Will default to 'cassandra-cluster'.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="cassandra-converter-ref" type="converterRef"
|
||||
use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The reference to a CassandraConverter instance. Default is null.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:simpleType name="clusterRef">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to type="com.datastax.driver.core.Cluster"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="converterRef">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to type="org.springframework.data.cassandra.convert.CassandraConverter"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:complexType name="poolingOptionsType">
|
||||
<xsd:attribute name="min-simultaneous-requests"
|
||||
type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
if the utilisation of opened connections drops below by this configured threshold, then cassandra drops connections till core-connections.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="max-simultaneous-requests"
|
||||
type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
If the utilisation of connections reaches this configurable threshold, then cassandra creates more connections up to max-connections.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="core-connections" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
For each host, the driver keeps a core amount of connections open at all time.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="max-connections" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
More connections are created up to a configurable maximum number of connections.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="socketOptionsType">
|
||||
<xsd:attribute name="connect-timeout-mls" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Sets connection timeout for client socket in milliseconds.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="keep-alive" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Sets the SO_KEEPALIVE socket option.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="reuse-address" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Sets the SO_REUSEADDR socket option.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="so-linger" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Sets the SO_LINGER socket option.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="tcp-no-delay" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Sets the SO_TCPNODELAY socket option.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="receive-buffer-size" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Sets the SO_RCVBUF socket option.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="send-buffer-size" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Sets the SO_SNDBUF socket option.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="keyspaceAttributesType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="table" type="tableType" maxOccurs="unbounded" minOccurs="0"></xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="auto" default="validate">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The keyspace manipulation operation on startup. Default value is 'validate'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="validate">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Validate the keyspace, makes no changes.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:enumeration>
|
||||
<xsd:enumeration value="update">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Update the keyspace.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:enumeration>
|
||||
<xsd:enumeration value="create">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Creates the keyspace, destroying previous data.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:enumeration>
|
||||
<xsd:enumeration value="create-drop">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Creates and then drop the keyspace at the end of the session.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:enumeration>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="replication-stategy" type="xsd:string"
|
||||
use="optional" default="SimpleStrategy">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Replication strategy of the Cassandra keyspace. Default value is 'SimpleStrategy'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="replication-factor" type="xsd:string"
|
||||
use="optional" default="1">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Replication factor used by the Cassandra keyspace. Default value is '1'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="durable-writes" type="xsd:string"
|
||||
use="optional" default="true">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Support durable writes in the Cassandra keyspace. Default value is 'true'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="tableType">
|
||||
<xsd:attribute name="entity" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Entity class name.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="name" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Table name override.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:schema>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 581 B |
@@ -0,0 +1,35 @@
|
||||
package org.springframework.data.cassandra.config;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.cassandra.core.Keyspace;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.datastax.driver.core.Cluster;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class CassandraNamespaceTests {
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext ctx;
|
||||
|
||||
@Test
|
||||
public void testSingleton() throws Exception {
|
||||
Object cluster = ctx.getBean("cassandra-cluster");
|
||||
Assert.notNull(cluster);
|
||||
Assert.isInstanceOf(Cluster.class, cluster);
|
||||
Object ks = ctx.getBean("cassandra-keyspace");
|
||||
Assert.notNull(ks);
|
||||
Assert.isInstanceOf(Keyspace.class, ks);
|
||||
|
||||
|
||||
Cluster c = (Cluster) cluster;
|
||||
System.out.println(org.apache.commons.beanutils.BeanUtils.describe(c.getConfiguration()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.springframework.data.cassandra.config;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.datastax.driver.core.Cluster;
|
||||
import com.datastax.driver.core.Session;
|
||||
|
||||
public class DriverTests {
|
||||
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
|
||||
Cluster.Builder builder = Cluster.builder().addContactPoint("127.0.0.1");
|
||||
|
||||
//builder.withCompression(ProtocolOptions.Compression.SNAPPY);
|
||||
|
||||
Cluster cluster = builder.build();
|
||||
|
||||
Session session = cluster.connect();
|
||||
|
||||
session.shutdown();
|
||||
|
||||
cluster.shutdown();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.mapping;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
|
||||
|
||||
/**
|
||||
* Unit tests for {@link BasicCassandraPersistentEntity}.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class BasicCassandraPersistentEntityUnitTests {
|
||||
|
||||
|
||||
@Mock
|
||||
ApplicationContext context;
|
||||
|
||||
@Test
|
||||
public void subclassInheritsAtDocumentAnnotation() {
|
||||
|
||||
BasicCassandraPersistentEntity<Notification> entity = new BasicCassandraPersistentEntity<Notification>(
|
||||
ClassTypeInformation.from(Notification.class));
|
||||
assertThat(entity.getTable(), is("messages"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void evaluatesSpELExpression() {
|
||||
|
||||
BasicCassandraPersistentEntity<Area> entity = new BasicCassandraPersistentEntity<Area>(
|
||||
ClassTypeInformation.from(Area.class));
|
||||
assertThat(entity.getTable(), is("123"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void collectionAllowsReferencingSpringBean() {
|
||||
|
||||
MappingBean bean = new MappingBean();
|
||||
bean.userLine = "user_line";
|
||||
|
||||
when(context.getBean("mappingBean")).thenReturn(bean);
|
||||
when(context.containsBean("mappingBean")).thenReturn(true);
|
||||
|
||||
BasicCassandraPersistentEntity<UserLine> entity = new BasicCassandraPersistentEntity<UserLine>(
|
||||
ClassTypeInformation.from(UserLine.class));
|
||||
entity.setApplicationContext(context);
|
||||
|
||||
assertThat(entity.getTable(), is("user_line"));
|
||||
}
|
||||
|
||||
@Table(name = "messages")
|
||||
class Message {
|
||||
|
||||
}
|
||||
|
||||
class Notification extends Message {
|
||||
|
||||
}
|
||||
|
||||
@Table(name = "#{123}")
|
||||
class Area {
|
||||
|
||||
}
|
||||
|
||||
@Table(name = "#{mappingBean.userLine}")
|
||||
class UserLine {
|
||||
|
||||
}
|
||||
|
||||
class MappingBean {
|
||||
|
||||
String userLine;
|
||||
|
||||
public String getUserLine() {
|
||||
return userLine;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.mapping;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Date;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@link BasicCassandraPersistentProperty}.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class BasicCassandraPersistentPropertyUnitTests {
|
||||
|
||||
CassandraPersistentEntity<Timeline> entity;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
entity = new BasicCassandraPersistentEntity<Timeline>(ClassTypeInformation.from(Timeline.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void usesAnnotatedColumnName() {
|
||||
|
||||
Field field = ReflectionUtils.findField(Timeline.class, "text");
|
||||
assertThat(getPropertyFor(field).getColumnName(), is("message"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checksIdProperty() {
|
||||
Field field = ReflectionUtils.findField(Timeline.class, "id");
|
||||
CassandraPersistentProperty property = getPropertyFor(field);
|
||||
assertThat(property.isIdProperty(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsPropertyNameForUnannotatedProperties() {
|
||||
Field field = ReflectionUtils.findField(Timeline.class, "time");
|
||||
assertThat(getPropertyFor(field).getColumnName(), is("time"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checksColumnIdProperty() {
|
||||
CassandraPersistentProperty property = getPropertyFor(ReflectionUtils.findField(Timeline.class, "time"));
|
||||
assertThat(property.isColumnId(), is(true));
|
||||
}
|
||||
|
||||
private CassandraPersistentProperty getPropertyFor(Field field) {
|
||||
return new BasicCassandraPersistentProperty(field, null, entity, new SimpleTypeHolder());
|
||||
}
|
||||
|
||||
class Timeline {
|
||||
|
||||
@Id
|
||||
String id;
|
||||
|
||||
@ColumnId
|
||||
Date time;
|
||||
|
||||
@Column("message")
|
||||
String text;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.test;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.cassandra.mapping.ColumnId;
|
||||
import org.springframework.data.cassandra.mapping.Qualify;
|
||||
import org.springframework.data.cassandra.mapping.Table;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
|
||||
/**
|
||||
* This is an example of dynamic table that creates each time new column
|
||||
* with Post timestamp annotated by @ColumnId.
|
||||
*
|
||||
* It is possible to use a static table for posts and identify them by PostId(UUID),
|
||||
* but in this case we need to use MapReduce for Big Data to find posts for
|
||||
* particular user, so it is better to have index (userId) -> index (post time)
|
||||
* architecture. It helps a lot to build eventually a search index for the particular user.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
@Table(name = "comments")
|
||||
public class Comment {
|
||||
|
||||
/*
|
||||
* Primary Row ID
|
||||
*/
|
||||
@Id
|
||||
private String author;
|
||||
|
||||
/*
|
||||
* Column ID
|
||||
*/
|
||||
@ColumnId
|
||||
@Qualify(type=DataType.Name.TIMESTAMP)
|
||||
private Date time;
|
||||
|
||||
private String text;
|
||||
|
||||
@Qualify(type=DataType.Name.SET, typeArguments={DataType.Name.TEXT})
|
||||
private Set<String> likes;
|
||||
|
||||
/*
|
||||
* Reference to the Post
|
||||
*/
|
||||
private String postAuthor;
|
||||
private Date postTime;
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public Date getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(Date time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public Set<String> getLikes() {
|
||||
return likes;
|
||||
}
|
||||
|
||||
public void setLikes(Set<String> likes) {
|
||||
this.likes = likes;
|
||||
}
|
||||
|
||||
public String getPostAuthor() {
|
||||
return postAuthor;
|
||||
}
|
||||
|
||||
public void setPostAuthor(String postAuthor) {
|
||||
this.postAuthor = postAuthor;
|
||||
}
|
||||
|
||||
public Date getPostTime() {
|
||||
return postTime;
|
||||
}
|
||||
|
||||
public void setPostTime(Date postTime) {
|
||||
this.postTime = postTime;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.test;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.cassandra.mapping.ColumnId;
|
||||
import org.springframework.data.cassandra.mapping.Index;
|
||||
import org.springframework.data.cassandra.mapping.Table;
|
||||
|
||||
/**
|
||||
* This is an example of dynamic table that creates each time new column
|
||||
* with Notification timestamp annotated by @ColumnId.
|
||||
*
|
||||
* By default it is active Notification until user deactivate it.
|
||||
* This table uses index on the field active to access in WHERE cause only
|
||||
* for active notifications.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
@Table(name = "notifications")
|
||||
public class Notification {
|
||||
|
||||
/*
|
||||
* Primary Row ID
|
||||
*/
|
||||
@Id
|
||||
private String username;
|
||||
|
||||
/*
|
||||
* Column ID
|
||||
*/
|
||||
@ColumnId
|
||||
private Date time;
|
||||
|
||||
@Index
|
||||
private boolean active;
|
||||
|
||||
/*
|
||||
* Reference data
|
||||
*/
|
||||
|
||||
private String type; // comment, post
|
||||
private String refAuthor;
|
||||
private Date refTime;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public Date getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(Date time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getRefAuthor() {
|
||||
return refAuthor;
|
||||
}
|
||||
|
||||
public void setRefAuthor(String refAuthor) {
|
||||
this.refAuthor = refAuthor;
|
||||
}
|
||||
|
||||
public Date getRefTime() {
|
||||
return refTime;
|
||||
}
|
||||
|
||||
public void setRefTime(Date refTime) {
|
||||
this.refTime = refTime;
|
||||
}
|
||||
|
||||
}
|
||||
124
src/test/java/org/springframework/data/cassandra/test/Post.java
Normal file
124
src/test/java/org/springframework/data/cassandra/test/Post.java
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.test;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.cassandra.mapping.ColumnId;
|
||||
import org.springframework.data.cassandra.mapping.Table;
|
||||
|
||||
/**
|
||||
* This is an example of dynamic table that creates each time new column
|
||||
* with Post timestamp annotated by @ColumnId.
|
||||
*
|
||||
* It is possible to use a static table for posts and identify them by PostId(UUID),
|
||||
* but in this case we need to use MapReduce for Big Data to find posts for
|
||||
* particular user, so it is better to have index (userId) -> index (post time)
|
||||
* architecture. It helps a lot to build eventually a search index for the particular user.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
@Table(name = "posts")
|
||||
public class Post {
|
||||
|
||||
/*
|
||||
* Primary Row ID
|
||||
*/
|
||||
@Id
|
||||
private String author;
|
||||
|
||||
/*
|
||||
* Column ID
|
||||
*/
|
||||
@ColumnId
|
||||
private Date time;
|
||||
|
||||
private String type; // status, share
|
||||
|
||||
private String text;
|
||||
private Set<String> resources;
|
||||
private Map<Date, String> comments;
|
||||
private Set<String> likes;
|
||||
private Set<String> followers;
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public Date getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(Date time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public Set<String> getResources() {
|
||||
return resources;
|
||||
}
|
||||
|
||||
public void setResources(Set<String> resources) {
|
||||
this.resources = resources;
|
||||
}
|
||||
|
||||
public Map<Date, String> getComments() {
|
||||
return comments;
|
||||
}
|
||||
|
||||
public void setComments(Map<Date, String> comments) {
|
||||
this.comments = comments;
|
||||
}
|
||||
|
||||
public Set<String> getLikes() {
|
||||
return likes;
|
||||
}
|
||||
|
||||
public void setLikes(Set<String> likes) {
|
||||
this.likes = likes;
|
||||
}
|
||||
|
||||
public Set<String> getFollowers() {
|
||||
return followers;
|
||||
}
|
||||
|
||||
public void setFollowers(Set<String> followers) {
|
||||
this.followers = followers;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.test;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.cassandra.mapping.ColumnId;
|
||||
import org.springframework.data.cassandra.mapping.Table;
|
||||
|
||||
/**
|
||||
* This is an example of the users timeline dynamic table, where all columns
|
||||
* are dynamically created by @ColumnId field value. The rest fields are places
|
||||
* in Cassandra value.
|
||||
*
|
||||
* Timeline entity is used to store user's status updates that it follows in the site.
|
||||
* Timeline always ordered by @ColumnId field and we can retrieve last top status
|
||||
* updates by using limits.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
@Table(name="timeline")
|
||||
public class Timeline {
|
||||
|
||||
/*
|
||||
* Primary Row ID
|
||||
*/
|
||||
@Id
|
||||
private String username;
|
||||
|
||||
/*
|
||||
* Column ID
|
||||
*/
|
||||
@ColumnId
|
||||
private Date time;
|
||||
|
||||
/*
|
||||
* Reference to the post by author and postUID
|
||||
*/
|
||||
private String author;
|
||||
private Date postTime;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public Date getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(Date time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public Date getPostTime() {
|
||||
return postTime;
|
||||
}
|
||||
|
||||
public void setPostTime(Date postTime) {
|
||||
this.postTime = postTime;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
139
src/test/java/org/springframework/data/cassandra/test/User.java
Normal file
139
src/test/java/org/springframework/data/cassandra/test/User.java
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.test;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.cassandra.mapping.Index;
|
||||
import org.springframework.data.cassandra.mapping.Table;
|
||||
|
||||
/**
|
||||
* This is an example of the Users statis table, where all fields are columns
|
||||
* in Cassandra row. Some fields can be Set,List,Map like emails.
|
||||
*
|
||||
* User contains base information related for separate user, like
|
||||
* names, additional information, emails, following users, friends.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
@Table(name="users")
|
||||
public class User {
|
||||
|
||||
/*
|
||||
* Primary Row ID
|
||||
*/
|
||||
@Id
|
||||
private String username;
|
||||
|
||||
/*
|
||||
* Public information
|
||||
*/
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
|
||||
/*
|
||||
* Secondary index, used only on fields with common information,
|
||||
* not effective on email, username
|
||||
*/
|
||||
@Index
|
||||
private String place;
|
||||
|
||||
/*
|
||||
* User emails
|
||||
*/
|
||||
private Set<String> emails;
|
||||
|
||||
/*
|
||||
* Password
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/*
|
||||
* Following other users in userline
|
||||
*/
|
||||
private Set<String> following;
|
||||
|
||||
/*
|
||||
* Friends of the user
|
||||
*/
|
||||
private Set<String> friends;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public String getPlace() {
|
||||
return place;
|
||||
}
|
||||
|
||||
public void setPlace(String place) {
|
||||
this.place = place;
|
||||
}
|
||||
|
||||
public Set<String> getEmails() {
|
||||
return emails;
|
||||
}
|
||||
|
||||
public void setEmails(Set<String> emails) {
|
||||
this.emails = emails;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public Set<String> getFollowing() {
|
||||
return following;
|
||||
}
|
||||
|
||||
public void setFollowing(Set<String> following) {
|
||||
this.following = following;
|
||||
}
|
||||
|
||||
public Set<String> getFriends() {
|
||||
return friends;
|
||||
}
|
||||
|
||||
public void setFriends(Set<String> friends) {
|
||||
this.friends = friends;
|
||||
}
|
||||
|
||||
}
|
||||
6
src/test/resources/log4j.properties
Normal file
6
src/test/resources/log4j.properties
Normal file
@@ -0,0 +1,6 @@
|
||||
log4j.rootLogger=WARN, stdout
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
|
||||
log4j.logger.org.springframework.data.cassandra=INFO
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cassandra="http://www.springframework.org/schema/data/cassandra"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/data/cassandra http://www.springframework.org/schema/data/cassandra/spring-cassandra-1.0.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
<context:property-placeholder
|
||||
location="classpath:/org/springframework/data/cassandra/config/cassandra.properties" />
|
||||
|
||||
<cassandra:cluster id="cassandra-cluster"
|
||||
contactPoints="${cassandra.contactPoints}" port="${cassandra.port}"
|
||||
compression="snappy">
|
||||
<cassandra:local-pooling-options
|
||||
min-simultaneous-requests="25" max-simultaneous-requests="100"
|
||||
core-connections="2" max-connections="8" />
|
||||
<cassandra:remote-pooling-options
|
||||
min-simultaneous-requests="25" max-simultaneous-requests="100"
|
||||
core-connections="1" max-connections="2" />
|
||||
<cassandra:socket-options
|
||||
connect-timeout-mls="5000" keep-alive="true" reuse-address="true"
|
||||
so-linger="60" tcp-no-delay="true" receive-buffer-size="65536"
|
||||
send-buffer-size="65536" />
|
||||
</cassandra:cluster>
|
||||
|
||||
<bean id="cassandra-mapping" class=" org.springframework.data.cassandra.mapping.CassandraMappingContext" />
|
||||
|
||||
<bean id="cassandra-converter" class=" org.springframework.data.cassandra.convert.MappingCassandraConverter">
|
||||
<constructor-arg ref="cassandra-mapping" />
|
||||
</bean>
|
||||
|
||||
<cassandra:keyspace id="cassandra-keyspace" name="${cassandra.keyspace}"
|
||||
cassandra-cluster-ref="cassandra-cluster" cassandra-converter-ref="cassandra-converter">
|
||||
<cassandra:keyspace-attributes auto="update" replication-stategy="SimpleStrategy" replication-factor="1" durable-writes="true">
|
||||
<cassandra:table entity="org.springframework.data.cassandra.test.Comment" />
|
||||
<cassandra:table entity="org.springframework.data.cassandra.test.Notification" />
|
||||
<cassandra:table entity="org.springframework.data.cassandra.test.Post" />
|
||||
<cassandra:table entity="org.springframework.data.cassandra.test.Timeline" />
|
||||
<cassandra:table entity="org.springframework.data.cassandra.test.User" />
|
||||
</cassandra:keyspace-attributes>
|
||||
</cassandra:keyspace>
|
||||
|
||||
<bean id="cassandraTemplate"
|
||||
class="org.springframework.data.cassandra.core.CassandraTemplate">
|
||||
<constructor-arg ref="cassandra-keyspace" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,7 @@
|
||||
cassandra.contactPoints=localhost
|
||||
cassandra.port=9042
|
||||
cassandra.keyspace=TestKS123
|
||||
|
||||
|
||||
|
||||
|
||||
30
template.mf
Normal file
30
template.mf
Normal file
@@ -0,0 +1,30 @@
|
||||
Bundle-SymbolicName: org.springframework.data.cassandra
|
||||
Bundle-Name: Spring Data Cassandra
|
||||
Bundle-Vendor: Mirantis
|
||||
Bundle-ManifestVersion: 2
|
||||
Import-Package:
|
||||
sun.reflect;version="0";resolution:=optional
|
||||
Import-Template:
|
||||
org.springframework.beans.*;version="[3.1.0, 4.0.0)",
|
||||
org.springframework.cache.*;version="[3.1.0, 4.0.0)",
|
||||
org.springframework.context.*;version="[3.1.0, 4.0.0)",
|
||||
org.springframework.core.*;version="[3.1.0, 4.0.0)",
|
||||
org.springframework.dao.*;version="[3.1.0, 4.0.0)",
|
||||
org.springframework.scheduling.*;resolution:="optional";version="[3.1.0, 4.0.0)",
|
||||
org.springframework.util.*;version="[3.1.0, 4.0.0)",
|
||||
org.springframework.oxm.*;resolution:="optional";version="[3.1.0, 4.0.0)",
|
||||
org.springframework.transaction.support.*;version="[3.1.0, 4.0.0)",
|
||||
org.springframework.data.*;version="[1.5.0, 2.0.0)",
|
||||
org.springframework.expression.*;version="[3.1.0, 4.0.0)",
|
||||
org.aopalliance.*;version="[1.0.0, 2.0.0)";resolution:=optional,
|
||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||
org.w3c.dom.*;version="0",
|
||||
javax.xml.transform.*;resolution:="optional";version="0",
|
||||
com.datastax.driver.core.*;resolution:="optional";version="[0.1.0, 1.0.0)",
|
||||
org.apache.cassandra.db.marshal.*;version="[1.2.0, 1.3.0)",
|
||||
org.slf4j.*;version="[1.5.0, 1.8.0)",
|
||||
org.idevlab.rjc.*;resolution:="optional";version="[0.6.4, 0.6.4]",
|
||||
org.apache.commons.pool.impl.*;resolution:="optional";version="[1.0.0, 3.0.0)",
|
||||
org.codehaus.jackson.*;resolution:="optional";version="[1.6, 2.0.0)",
|
||||
org.apache.commons.beanutils.*;resolution:="optional";version=1.8.5,
|
||||
com.google.common.*;resolution:="optional";version="[11.0.0, 20.0.0)"
|
||||
664
test-support/cassandra/conf/cassandra.yaml
Normal file
664
test-support/cassandra/conf/cassandra.yaml
Normal file
@@ -0,0 +1,664 @@
|
||||
# Cassandra storage config YAML
|
||||
|
||||
# NOTE:
|
||||
# See http://wiki.apache.org/cassandra/StorageConfiguration for
|
||||
# full explanations of configuration directives
|
||||
# /NOTE
|
||||
|
||||
# The name of the cluster. This is mainly used to prevent machines in
|
||||
# one logical cluster from joining another.
|
||||
cluster_name: 'Test Cluster'
|
||||
|
||||
# This defines the number of tokens randomly assigned to this node on the ring
|
||||
# The more tokens, relative to other nodes, the larger the proportion of data
|
||||
# that this node will store. You probably want all nodes to have the same number
|
||||
# of tokens assuming they have equal hardware capability.
|
||||
#
|
||||
# If you leave this unspecified, Cassandra will use the default of 1 token for legacy compatibility,
|
||||
# and will use the initial_token as described below.
|
||||
#
|
||||
# Specifying initial_token will override this setting.
|
||||
#
|
||||
# If you already have a cluster with 1 token per node, and wish to migrate to
|
||||
# multiple tokens per node, see http://wiki.apache.org/cassandra/Operations
|
||||
num_tokens: 256
|
||||
|
||||
# initial_token allows you to specify tokens manually. While you can use # it with
|
||||
# vnodes (num_tokens > 1, above) -- in which case you should provide a
|
||||
# comma-separated list -- it's primarily used when adding nodes # to legacy clusters
|
||||
# that do not have vnodes enabled.
|
||||
# initial_token:
|
||||
|
||||
# See http://wiki.apache.org/cassandra/HintedHandoff
|
||||
hinted_handoff_enabled: true
|
||||
# this defines the maximum amount of time a dead host will have hints
|
||||
# generated. After it has been dead this long, new hints for it will not be
|
||||
# created until it has been seen alive and gone down again.
|
||||
max_hint_window_in_ms: 10800000 # 3 hours
|
||||
# Maximum throttle in KBs per second, per delivery thread. This will be
|
||||
# reduced proportionally to the number of nodes in the cluster. (If there
|
||||
# are two nodes in the cluster, each delivery thread will use the maximum
|
||||
# rate; if there are three, each will throttle to half of the maximum,
|
||||
# since we expect two nodes to be delivering hints simultaneously.)
|
||||
hinted_handoff_throttle_in_kb: 1024
|
||||
# Number of threads with which to deliver hints;
|
||||
# Consider increasing this number when you have multi-dc deployments, since
|
||||
# cross-dc handoff tends to be slower
|
||||
max_hints_delivery_threads: 2
|
||||
|
||||
# The following setting populates the page cache on memtable flush and compaction
|
||||
# WARNING: Enable this setting only when the whole node's data fits in memory.
|
||||
# Defaults to: false
|
||||
# populate_io_cache_on_flush: false
|
||||
|
||||
# Authentication backend, implementing IAuthenticator; used to identify users
|
||||
# Out of the box, Cassandra provides org.apache.cassandra.auth.{AllowAllAuthenticator,
|
||||
# PasswordAuthenticator}.
|
||||
#
|
||||
# - AllowAllAuthenticator performs no checks - set it to disable authentication.
|
||||
# - PasswordAuthenticator relies on username/password pairs to authenticate
|
||||
# users. It keeps usernames and hashed passwords in system_auth.credentials table.
|
||||
# Please increase system_auth keyspace replication factor if you use this authenticator.
|
||||
authenticator: AllowAllAuthenticator
|
||||
|
||||
# Authorization backend, implementing IAuthorizer; used to limit access/provide permissions
|
||||
# Out of the box, Cassandra provides org.apache.cassandra.auth.{AllowAllAuthorizer,
|
||||
# CassandraAuthorizer}.
|
||||
#
|
||||
# - AllowAllAuthorizer allows any action to any user - set it to disable authorization.
|
||||
# - CassandraAuthorizer stores permissions in system_auth.permissions table. Please
|
||||
# increase system_auth keyspace replication factor if you use this authorizer.
|
||||
authorizer: AllowAllAuthorizer
|
||||
|
||||
# Validity period for permissions cache (fetching permissions can be an
|
||||
# expensive operation depending on the authorizer, CassandraAuthorizer is
|
||||
# one example). Defaults to 2000, set to 0 to disable.
|
||||
# Will be disabled automatically for AllowAllAuthorizer.
|
||||
permissions_validity_in_ms: 2000
|
||||
|
||||
# The partitioner is responsible for distributing rows (by key) across
|
||||
# nodes in the cluster. Any IPartitioner may be used, including your
|
||||
# own as long as it is on the classpath. Out of the box, Cassandra
|
||||
# provides org.apache.cassandra.dht.{Murmur3Partitioner, RandomPartitioner
|
||||
# ByteOrderedPartitioner, OrderPreservingPartitioner (deprecated)}.
|
||||
#
|
||||
# - RandomPartitioner distributes rows across the cluster evenly by md5.
|
||||
# This is the default prior to 1.2 and is retained for compatibility.
|
||||
# - Murmur3Partitioner is similar to RandomPartioner but uses Murmur3_128
|
||||
# Hash Function instead of md5. When in doubt, this is the best option.
|
||||
# - ByteOrderedPartitioner orders rows lexically by key bytes. BOP allows
|
||||
# scanning rows in key order, but the ordering can generate hot spots
|
||||
# for sequential insertion workloads.
|
||||
# - OrderPreservingPartitioner is an obsolete form of BOP, that stores
|
||||
# - keys in a less-efficient format and only works with keys that are
|
||||
# UTF8-encoded Strings.
|
||||
# - CollatingOPP collates according to EN,US rules rather than lexical byte
|
||||
# ordering. Use this as an example if you need custom collation.
|
||||
#
|
||||
# See http://wiki.apache.org/cassandra/Operations for more on
|
||||
# partitioners and token selection.
|
||||
partitioner: org.apache.cassandra.dht.Murmur3Partitioner
|
||||
|
||||
# Directories where Cassandra should store data on disk. Cassandra
|
||||
# will spread data evenly across them, subject to the granularity of
|
||||
# the configured compaction strategy.
|
||||
data_file_directories:
|
||||
- .cassandra/var/lib/cassandra/data
|
||||
|
||||
# commit log
|
||||
commitlog_directory: .cassandra/var/lib/cassandra/commitlog
|
||||
|
||||
# policy for data disk failures:
|
||||
# stop: shut down gossip and Thrift, leaving the node effectively dead, but
|
||||
# can still be inspected via JMX.
|
||||
# best_effort: stop using the failed disk and respond to requests based on
|
||||
# remaining available sstables. This means you WILL see obsolete
|
||||
# data at CL.ONE!
|
||||
# ignore: ignore fatal errors and let requests fail, as in pre-1.2 Cassandra
|
||||
disk_failure_policy: stop
|
||||
|
||||
# Maximum size of the key cache in memory.
|
||||
#
|
||||
# Each key cache hit saves 1 seek and each row cache hit saves 2 seeks at the
|
||||
# minimum, sometimes more. The key cache is fairly tiny for the amount of
|
||||
# time it saves, so it's worthwhile to use it at large numbers.
|
||||
# The row cache saves even more time, but must contain the entire row,
|
||||
# so it is extremely space-intensive. It's best to only use the
|
||||
# row cache if you have hot rows or static rows.
|
||||
#
|
||||
# NOTE: if you reduce the size, you may not get you hottest keys loaded on startup.
|
||||
#
|
||||
# Default value is empty to make it "auto" (min(5% of Heap (in MB), 100MB)). Set to 0 to disable key cache.
|
||||
key_cache_size_in_mb:
|
||||
|
||||
# Duration in seconds after which Cassandra should
|
||||
# save the key cache. Caches are saved to saved_caches_directory as
|
||||
# specified in this configuration file.
|
||||
#
|
||||
# Saved caches greatly improve cold-start speeds, and is relatively cheap in
|
||||
# terms of I/O for the key cache. Row cache saving is much more expensive and
|
||||
# has limited use.
|
||||
#
|
||||
# Default is 14400 or 4 hours.
|
||||
key_cache_save_period: 14400
|
||||
|
||||
# Number of keys from the key cache to save
|
||||
# Disabled by default, meaning all keys are going to be saved
|
||||
# key_cache_keys_to_save: 100
|
||||
|
||||
# Maximum size of the row cache in memory.
|
||||
# NOTE: if you reduce the size, you may not get you hottest keys loaded on startup.
|
||||
#
|
||||
# Default value is 0, to disable row caching.
|
||||
row_cache_size_in_mb: 0
|
||||
|
||||
# Duration in seconds after which Cassandra should
|
||||
# safe the row cache. Caches are saved to saved_caches_directory as specified
|
||||
# in this configuration file.
|
||||
#
|
||||
# Saved caches greatly improve cold-start speeds, and is relatively cheap in
|
||||
# terms of I/O for the key cache. Row cache saving is much more expensive and
|
||||
# has limited use.
|
||||
#
|
||||
# Default is 0 to disable saving the row cache.
|
||||
row_cache_save_period: 0
|
||||
|
||||
# Number of keys from the row cache to save
|
||||
# Disabled by default, meaning all keys are going to be saved
|
||||
# row_cache_keys_to_save: 100
|
||||
|
||||
# The off-heap memory allocator. Affects storage engine metadata as
|
||||
# well as caches. Experiments show that JEMAlloc saves some memory
|
||||
# than the native GCC allocator (i.e., JEMalloc is more
|
||||
# fragmentation-resistant).
|
||||
#
|
||||
# Supported values are: NativeAllocator, JEMallocAllocator
|
||||
#
|
||||
# If you intend to use JEMallocAllocator you have to install JEMalloc as library and
|
||||
# modify cassandra-env.sh as directed in the file.
|
||||
#
|
||||
# Defaults to NativeAllocator
|
||||
# memory_allocator: NativeAllocator
|
||||
|
||||
# saved caches
|
||||
saved_caches_directory: .cassandra/var/lib/cassandra/saved_caches
|
||||
|
||||
# commitlog_sync may be either "periodic" or "batch."
|
||||
# When in batch mode, Cassandra won't ack writes until the commit log
|
||||
# has been fsynced to disk. It will wait up to
|
||||
# commitlog_sync_batch_window_in_ms milliseconds for other writes, before
|
||||
# performing the sync.
|
||||
#
|
||||
# commitlog_sync: batch
|
||||
# commitlog_sync_batch_window_in_ms: 50
|
||||
#
|
||||
# the other option is "periodic" where writes may be acked immediately
|
||||
# and the CommitLog is simply synced every commitlog_sync_period_in_ms
|
||||
# milliseconds. By default this allows 1024*(CPU cores) pending
|
||||
# entries on the commitlog queue. If you are writing very large blobs,
|
||||
# you should reduce that; 16*cores works reasonably well for 1MB blobs.
|
||||
# It should be at least as large as the concurrent_writes setting.
|
||||
commitlog_sync: periodic
|
||||
commitlog_sync_period_in_ms: 10000
|
||||
# commitlog_periodic_queue_size:
|
||||
|
||||
# The size of the individual commitlog file segments. A commitlog
|
||||
# segment may be archived, deleted, or recycled once all the data
|
||||
# in it (potentially from each columnfamily in the system) has been
|
||||
# flushed to sstables.
|
||||
#
|
||||
# The default size is 32, which is almost always fine, but if you are
|
||||
# archiving commitlog segments (see commitlog_archiving.properties),
|
||||
# then you probably want a finer granularity of archiving; 8 or 16 MB
|
||||
# is reasonable.
|
||||
commitlog_segment_size_in_mb: 32
|
||||
|
||||
# any class that implements the SeedProvider interface and has a
|
||||
# constructor that takes a Map<String, String> of parameters will do.
|
||||
seed_provider:
|
||||
# Addresses of hosts that are deemed contact points.
|
||||
# Cassandra nodes use this list of hosts to find each other and learn
|
||||
# the topology of the ring. You must change this if you are running
|
||||
# multiple nodes!
|
||||
- class_name: org.apache.cassandra.locator.SimpleSeedProvider
|
||||
parameters:
|
||||
# seeds is actually a comma-delimited list of addresses.
|
||||
# Ex: "<ip1>,<ip2>,<ip3>"
|
||||
- seeds: "127.0.0.1"
|
||||
|
||||
# For workloads with more data than can fit in memory, Cassandra's
|
||||
# bottleneck will be reads that need to fetch data from
|
||||
# disk. "concurrent_reads" should be set to (16 * number_of_drives) in
|
||||
# order to allow the operations to enqueue low enough in the stack
|
||||
# that the OS and drives can reorder them.
|
||||
#
|
||||
# On the other hand, since writes are almost never IO bound, the ideal
|
||||
# number of "concurrent_writes" is dependent on the number of cores in
|
||||
# your system; (8 * number_of_cores) is a good rule of thumb.
|
||||
concurrent_reads: 32
|
||||
concurrent_writes: 32
|
||||
|
||||
# Total memory to use for sstable-reading buffers. Defaults to
|
||||
# the smaller of 1/4 of heap or 512MB.
|
||||
# file_cache_size_in_mb: 512
|
||||
|
||||
# Total memory to use for memtables. Cassandra will flush the largest
|
||||
# memtable when this much memory is used.
|
||||
# If omitted, Cassandra will set it to 1/3 of the heap.
|
||||
# memtable_total_space_in_mb: 2048
|
||||
|
||||
# Total space to use for commitlogs. Since commitlog segments are
|
||||
# mmapped, and hence use up address space, the default size is 32
|
||||
# on 32-bit JVMs, and 1024 on 64-bit JVMs.
|
||||
#
|
||||
# If space gets above this value (it will round up to the next nearest
|
||||
# segment multiple), Cassandra will flush every dirty CF in the oldest
|
||||
# segment and remove it. So a small total commitlog space will tend
|
||||
# to cause more flush activity on less-active columnfamilies.
|
||||
# commitlog_total_space_in_mb: 4096
|
||||
|
||||
# This sets the amount of memtable flush writer threads. These will
|
||||
# be blocked by disk io, and each one will hold a memtable in memory
|
||||
# while blocked. If you have a large heap and many data directories,
|
||||
# you can increase this value for better flush performance.
|
||||
# By default this will be set to the amount of data directories defined.
|
||||
#memtable_flush_writers: 1
|
||||
|
||||
# the number of full memtables to allow pending flush, that is,
|
||||
# waiting for a writer thread. At a minimum, this should be set to
|
||||
# the maximum number of secondary indexes created on a single CF.
|
||||
memtable_flush_queue_size: 4
|
||||
|
||||
# Whether to, when doing sequential writing, fsync() at intervals in
|
||||
# order to force the operating system to flush the dirty
|
||||
# buffers. Enable this to avoid sudden dirty buffer flushing from
|
||||
# impacting read latencies. Almost always a good idea on SSDs; not
|
||||
# necessarily on platters.
|
||||
trickle_fsync: false
|
||||
trickle_fsync_interval_in_kb: 10240
|
||||
|
||||
# TCP port, for commands and data
|
||||
storage_port: 7000
|
||||
|
||||
# SSL port, for encrypted communication. Unused unless enabled in
|
||||
# encryption_options
|
||||
ssl_storage_port: 7001
|
||||
|
||||
# Address to bind to and tell other Cassandra nodes to connect to. You
|
||||
# _must_ change this if you want multiple nodes to be able to
|
||||
# communicate!
|
||||
#
|
||||
# Leaving it blank leaves it up to InetAddress.getLocalHost(). This
|
||||
# will always do the Right Thing _if_ the node is properly configured
|
||||
# (hostname, name resolution, etc), and the Right Thing is to use the
|
||||
# address associated with the hostname (it might not be).
|
||||
#
|
||||
# Setting this to 0.0.0.0 is always wrong.
|
||||
listen_address: localhost
|
||||
|
||||
# Address to broadcast to other Cassandra nodes
|
||||
# Leaving this blank will set it to the same value as listen_address
|
||||
# broadcast_address: 1.2.3.4
|
||||
|
||||
# Internode authentication backend, implementing IInternodeAuthenticator;
|
||||
# used to allow/disallow connections from peer nodes.
|
||||
# internode_authenticator: org.apache.cassandra.auth.AllowAllInternodeAuthenticator
|
||||
|
||||
# Whether to start the native transport server.
|
||||
# Please note that the address on which the native transport is bound is the
|
||||
# same as the rpc_address. The port however is different and specified below.
|
||||
start_native_transport: true
|
||||
# port for the CQL native transport to listen for clients on
|
||||
native_transport_port: 9042
|
||||
# The maximum threads for handling requests when the native transport is used.
|
||||
# This is similar to rpc_max_threads though the default differs slightly (and
|
||||
# there is no native_transport_min_threads, idle threads will always be stopped
|
||||
# after 30 seconds).
|
||||
# native_transport_max_threads: 128
|
||||
|
||||
# Whether to start the thrift rpc server.
|
||||
start_rpc: true
|
||||
|
||||
# The address to bind the Thrift RPC service and native transport
|
||||
# server -- clients connect here.
|
||||
#
|
||||
# Leaving this blank has the same effect it does for ListenAddress,
|
||||
# (i.e. it will be based on the configured hostname of the node).
|
||||
#
|
||||
# Note that unlike ListenAddress above, it is allowed to specify 0.0.0.0
|
||||
# here if you want to listen on all interfaces but is not best practice
|
||||
# as it is known to confuse the node auto-discovery features of some
|
||||
# client drivers.
|
||||
rpc_address: localhost
|
||||
# port for Thrift to listen for clients on
|
||||
rpc_port: 9160
|
||||
|
||||
# enable or disable keepalive on rpc connections
|
||||
rpc_keepalive: true
|
||||
|
||||
# Cassandra provides three out-of-the-box options for the RPC Server:
|
||||
#
|
||||
# sync -> One thread per thrift connection. For a very large number of clients, memory
|
||||
# will be your limiting factor. On a 64 bit JVM, 180KB is the minimum stack size
|
||||
# per thread, and that will correspond to your use of virtual memory (but physical memory
|
||||
# may be limited depending on use of stack space).
|
||||
#
|
||||
# hsha -> Stands for "half synchronous, half asynchronous." All thrift clients are handled
|
||||
# asynchronously using a small number of threads that does not vary with the amount
|
||||
# of thrift clients (and thus scales well to many clients). The rpc requests are still
|
||||
# synchronous (one thread per active request).
|
||||
#
|
||||
# The default is sync because on Windows hsha is about 30% slower. On Linux,
|
||||
# sync/hsha performance is about the same, with hsha of course using less memory.
|
||||
#
|
||||
# Alternatively, can provide your own RPC server by providing the fully-qualified class name
|
||||
# of an o.a.c.t.TServerFactory that can create an instance of it.
|
||||
rpc_server_type: sync
|
||||
|
||||
# Uncomment rpc_min|max_thread to set request pool size limits.
|
||||
#
|
||||
# Regardless of your choice of RPC server (see above), the number of maximum requests in the
|
||||
# RPC thread pool dictates how many concurrent requests are possible (but if you are using the sync
|
||||
# RPC server, it also dictates the number of clients that can be connected at all).
|
||||
#
|
||||
# The default is unlimited and thus provides no protection against clients overwhelming the server. You are
|
||||
# encouraged to set a maximum that makes sense for you in production, but do keep in mind that
|
||||
# rpc_max_threads represents the maximum number of client requests this server may execute concurrently.
|
||||
#
|
||||
# rpc_min_threads: 16
|
||||
# rpc_max_threads: 2048
|
||||
|
||||
# uncomment to set socket buffer sizes on rpc connections
|
||||
# rpc_send_buff_size_in_bytes:
|
||||
# rpc_recv_buff_size_in_bytes:
|
||||
|
||||
# Uncomment to set socket buffer size for internode communication
|
||||
# Note that when setting this, the buffer size is limited by net.core.wmem_max
|
||||
# and when not setting it it is defined by net.ipv4.tcp_wmem
|
||||
# See:
|
||||
# /proc/sys/net/core/wmem_max
|
||||
# /proc/sys/net/core/rmem_max
|
||||
# /proc/sys/net/ipv4/tcp_wmem
|
||||
# /proc/sys/net/ipv4/tcp_wmem
|
||||
# and: man tcp
|
||||
# internode_send_buff_size_in_bytes:
|
||||
# internode_recv_buff_size_in_bytes:
|
||||
|
||||
# Frame size for thrift (maximum message length).
|
||||
thrift_framed_transport_size_in_mb: 15
|
||||
|
||||
# Set to true to have Cassandra create a hard link to each sstable
|
||||
# flushed or streamed locally in a backups/ subdirectory of the
|
||||
# keyspace data. Removing these links is the operator's
|
||||
# responsibility.
|
||||
incremental_backups: false
|
||||
|
||||
# Whether or not to take a snapshot before each compaction. Be
|
||||
# careful using this option, since Cassandra won't clean up the
|
||||
# snapshots for you. Mostly useful if you're paranoid when there
|
||||
# is a data format change.
|
||||
snapshot_before_compaction: false
|
||||
|
||||
# Whether or not a snapshot is taken of the data before keyspace truncation
|
||||
# or dropping of column families. The STRONGLY advised default of true
|
||||
# should be used to provide data safety. If you set this flag to false, you will
|
||||
# lose data on truncation or drop.
|
||||
auto_snapshot: true
|
||||
|
||||
# Add column indexes to a row after its contents reach this size.
|
||||
# Increase if your column values are large, or if you have a very large
|
||||
# number of columns. The competing causes are, Cassandra has to
|
||||
# deserialize this much of the row to read a single column, so you want
|
||||
# it to be small - at least if you do many partial-row reads - but all
|
||||
# the index data is read for each access, so you don't want to generate
|
||||
# that wastefully either.
|
||||
column_index_size_in_kb: 64
|
||||
|
||||
# Size limit for rows being compacted in memory. Larger rows will spill
|
||||
# over to disk and use a slower two-pass compaction process. A message
|
||||
# will be logged specifying the row key.
|
||||
in_memory_compaction_limit_in_mb: 64
|
||||
|
||||
# Number of simultaneous compactions to allow, NOT including
|
||||
# validation "compactions" for anti-entropy repair. Simultaneous
|
||||
# compactions can help preserve read performance in a mixed read/write
|
||||
# workload, by mitigating the tendency of small sstables to accumulate
|
||||
# during a single long running compactions. The default is usually
|
||||
# fine and if you experience problems with compaction running too
|
||||
# slowly or too fast, you should look at
|
||||
# compaction_throughput_mb_per_sec first.
|
||||
#
|
||||
# concurrent_compactors defaults to the number of cores.
|
||||
# Uncomment to make compaction mono-threaded, the pre-0.8 default.
|
||||
#concurrent_compactors: 1
|
||||
|
||||
# Multi-threaded compaction. When enabled, each compaction will use
|
||||
# up to one thread per core, plus one thread per sstable being merged.
|
||||
# This is usually only useful for SSD-based hardware: otherwise,
|
||||
# your concern is usually to get compaction to do LESS i/o (see:
|
||||
# compaction_throughput_mb_per_sec), not more.
|
||||
multithreaded_compaction: false
|
||||
|
||||
# Throttles compaction to the given total throughput across the entire
|
||||
# system. The faster you insert data, the faster you need to compact in
|
||||
# order to keep the sstable count down, but in general, setting this to
|
||||
# 16 to 32 times the rate you are inserting data is more than sufficient.
|
||||
# Setting this to 0 disables throttling. Note that this account for all types
|
||||
# of compaction, including validation compaction.
|
||||
compaction_throughput_mb_per_sec: 16
|
||||
|
||||
# Track cached row keys during compaction, and re-cache their new
|
||||
# positions in the compacted sstable. Disable if you use really large
|
||||
# key caches.
|
||||
compaction_preheat_key_cache: true
|
||||
|
||||
# Throttles all outbound streaming file transfers on this node to the
|
||||
# given total throughput in Mbps. This is necessary because Cassandra does
|
||||
# mostly sequential IO when streaming data during bootstrap or repair, which
|
||||
# can lead to saturating the network connection and degrading rpc performance.
|
||||
# When unset, the default is 200 Mbps or 25 MB/s.
|
||||
# stream_throughput_outbound_megabits_per_sec: 200
|
||||
|
||||
# How long the coordinator should wait for read operations to complete
|
||||
read_request_timeout_in_ms: 5000
|
||||
# How long the coordinator should wait for seq or index scans to complete
|
||||
range_request_timeout_in_ms: 10000
|
||||
# How long the coordinator should wait for writes to complete
|
||||
write_request_timeout_in_ms: 2000
|
||||
# How long a coordinator should continue to retry a CAS operation
|
||||
# that contends with other proposals for the same row
|
||||
cas_contention_timeout_in_ms: 1000
|
||||
# How long the coordinator should wait for truncates to complete
|
||||
# (This can be much longer, because unless auto_snapshot is disabled
|
||||
# we need to flush first so we can snapshot before removing the data.)
|
||||
truncate_request_timeout_in_ms: 60000
|
||||
# The default timeout for other, miscellaneous operations
|
||||
request_timeout_in_ms: 10000
|
||||
|
||||
# Enable operation timeout information exchange between nodes to accurately
|
||||
# measure request timeouts. If disabled, replicas will assume that requests
|
||||
# were forwarded to them instantly by the coordinator, which means that
|
||||
# under overload conditions we will waste that much extra time processing
|
||||
# already-timed-out requests.
|
||||
#
|
||||
# Warning: before enabling this property make sure to ntp is installed
|
||||
# and the times are synchronized between the nodes.
|
||||
cross_node_timeout: false
|
||||
|
||||
# Enable socket timeout for streaming operation.
|
||||
# When a timeout occurs during streaming, streaming is retried from the start
|
||||
# of the current file. This _can_ involve re-streaming an important amount of
|
||||
# data, so you should avoid setting the value too low.
|
||||
# Default value is 0, which never timeout streams.
|
||||
# streaming_socket_timeout_in_ms: 0
|
||||
|
||||
# phi value that must be reached for a host to be marked down.
|
||||
# most users should never need to adjust this.
|
||||
# phi_convict_threshold: 8
|
||||
|
||||
# endpoint_snitch -- Set this to a class that implements
|
||||
# IEndpointSnitch. The snitch has two functions:
|
||||
# - it teaches Cassandra enough about your network topology to route
|
||||
# requests efficiently
|
||||
# - it allows Cassandra to spread replicas around your cluster to avoid
|
||||
# correlated failures. It does this by grouping machines into
|
||||
# "datacenters" and "racks." Cassandra will do its best not to have
|
||||
# more than one replica on the same "rack" (which may not actually
|
||||
# be a physical location)
|
||||
#
|
||||
# IF YOU CHANGE THE SNITCH AFTER DATA IS INSERTED INTO THE CLUSTER,
|
||||
# YOU MUST RUN A FULL REPAIR, SINCE THE SNITCH AFFECTS WHERE REPLICAS
|
||||
# ARE PLACED.
|
||||
#
|
||||
# Out of the box, Cassandra provides
|
||||
# - SimpleSnitch:
|
||||
# Treats Strategy order as proximity. This improves cache locality
|
||||
# when disabling read repair, which can further improve throughput.
|
||||
# Only appropriate for single-datacenter deployments.
|
||||
# - PropertyFileSnitch:
|
||||
# Proximity is determined by rack and data center, which are
|
||||
# explicitly configured in cassandra-topology.properties.
|
||||
# - GossipingPropertyFileSnitch
|
||||
# The rack and datacenter for the local node are defined in
|
||||
# cassandra-rackdc.properties and propagated to other nodes via gossip. If
|
||||
# cassandra-topology.properties exists, it is used as a fallback, allowing
|
||||
# migration from the PropertyFileSnitch.
|
||||
# - RackInferringSnitch:
|
||||
# Proximity is determined by rack and data center, which are
|
||||
# assumed to correspond to the 3rd and 2nd octet of each node's
|
||||
# IP address, respectively. Unless this happens to match your
|
||||
# deployment conventions (as it did Facebook's), this is best used
|
||||
# as an example of writing a custom Snitch class.
|
||||
# - Ec2Snitch:
|
||||
# Appropriate for EC2 deployments in a single Region. Loads Region
|
||||
# and Availability Zone information from the EC2 API. The Region is
|
||||
# treated as the datacenter, and the Availability Zone as the rack.
|
||||
# Only private IPs are used, so this will not work across multiple
|
||||
# Regions.
|
||||
# - Ec2MultiRegionSnitch:
|
||||
# Uses public IPs as broadcast_address to allow cross-region
|
||||
# connectivity. (Thus, you should set seed addresses to the public
|
||||
# IP as well.) You will need to open the storage_port or
|
||||
# ssl_storage_port on the public IP firewall. (For intra-Region
|
||||
# traffic, Cassandra will switch to the private IP after
|
||||
# establishing a connection.)
|
||||
#
|
||||
# You can use a custom Snitch by setting this to the full class name
|
||||
# of the snitch, which will be assumed to be on your classpath.
|
||||
endpoint_snitch: SimpleSnitch
|
||||
|
||||
# controls how often to perform the more expensive part of host score
|
||||
# calculation
|
||||
dynamic_snitch_update_interval_in_ms: 100
|
||||
# controls how often to reset all host scores, allowing a bad host to
|
||||
# possibly recover
|
||||
dynamic_snitch_reset_interval_in_ms: 600000
|
||||
# if set greater than zero and read_repair_chance is < 1.0, this will allow
|
||||
# 'pinning' of replicas to hosts in order to increase cache capacity.
|
||||
# The badness threshold will control how much worse the pinned host has to be
|
||||
# before the dynamic snitch will prefer other replicas over it. This is
|
||||
# expressed as a double which represents a percentage. Thus, a value of
|
||||
# 0.2 means Cassandra would continue to prefer the static snitch values
|
||||
# until the pinned host was 20% worse than the fastest.
|
||||
dynamic_snitch_badness_threshold: 0.1
|
||||
|
||||
# request_scheduler -- Set this to a class that implements
|
||||
# RequestScheduler, which will schedule incoming client requests
|
||||
# according to the specific policy. This is useful for multi-tenancy
|
||||
# with a single Cassandra cluster.
|
||||
# NOTE: This is specifically for requests from the client and does
|
||||
# not affect inter node communication.
|
||||
# org.apache.cassandra.scheduler.NoScheduler - No scheduling takes place
|
||||
# org.apache.cassandra.scheduler.RoundRobinScheduler - Round robin of
|
||||
# client requests to a node with a separate queue for each
|
||||
# request_scheduler_id. The scheduler is further customized by
|
||||
# request_scheduler_options as described below.
|
||||
request_scheduler: org.apache.cassandra.scheduler.NoScheduler
|
||||
|
||||
# Scheduler Options vary based on the type of scheduler
|
||||
# NoScheduler - Has no options
|
||||
# RoundRobin
|
||||
# - throttle_limit -- The throttle_limit is the number of in-flight
|
||||
# requests per client. Requests beyond
|
||||
# that limit are queued up until
|
||||
# running requests can complete.
|
||||
# The value of 80 here is twice the number of
|
||||
# concurrent_reads + concurrent_writes.
|
||||
# - default_weight -- default_weight is optional and allows for
|
||||
# overriding the default which is 1.
|
||||
# - weights -- Weights are optional and will default to 1 or the
|
||||
# overridden default_weight. The weight translates into how
|
||||
# many requests are handled during each turn of the
|
||||
# RoundRobin, based on the scheduler id.
|
||||
#
|
||||
# request_scheduler_options:
|
||||
# throttle_limit: 80
|
||||
# default_weight: 5
|
||||
# weights:
|
||||
# Keyspace1: 1
|
||||
# Keyspace2: 5
|
||||
|
||||
# request_scheduler_id -- An identifier based on which to perform
|
||||
# the request scheduling. Currently the only valid option is keyspace.
|
||||
# request_scheduler_id: keyspace
|
||||
|
||||
# Enable or disable inter-node encryption
|
||||
# Default settings are TLS v1, RSA 1024-bit keys (it is imperative that
|
||||
# users generate their own keys) TLS_RSA_WITH_AES_128_CBC_SHA as the cipher
|
||||
# suite for authentication, key exchange and encryption of the actual data transfers.
|
||||
# NOTE: No custom encryption options are enabled at the moment
|
||||
# The available internode options are : all, none, dc, rack
|
||||
#
|
||||
# If set to dc cassandra will encrypt the traffic between the DCs
|
||||
# If set to rack cassandra will encrypt the traffic between the racks
|
||||
#
|
||||
# The passwords used in these options must match the passwords used when generating
|
||||
# the keystore and truststore. For instructions on generating these files, see:
|
||||
# http://download.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#CreateKeystore
|
||||
#
|
||||
server_encryption_options:
|
||||
internode_encryption: none
|
||||
keystore: conf/.keystore
|
||||
keystore_password: cassandra
|
||||
truststore: conf/.truststore
|
||||
truststore_password: cassandra
|
||||
# More advanced defaults below:
|
||||
# protocol: TLS
|
||||
# algorithm: SunX509
|
||||
# store_type: JKS
|
||||
# cipher_suites: [TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA]
|
||||
# require_client_auth: false
|
||||
|
||||
# enable or disable client/server encryption.
|
||||
client_encryption_options:
|
||||
enabled: false
|
||||
keystore: conf/.keystore
|
||||
keystore_password: cassandra
|
||||
# require_client_auth: false
|
||||
# Set trustore and truststore_password if require_client_auth is true
|
||||
# truststore: conf/.truststore
|
||||
# truststore_password: cassandra
|
||||
# More advanced defaults below:
|
||||
# protocol: TLS
|
||||
# algorithm: SunX509
|
||||
# store_type: JKS
|
||||
# cipher_suites: [TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA]
|
||||
|
||||
# internode_compression controls whether traffic between nodes is
|
||||
# compressed.
|
||||
# can be: all - all traffic is compressed
|
||||
# dc - traffic between different datacenters is compressed
|
||||
# none - nothing is compressed.
|
||||
internode_compression: all
|
||||
|
||||
# Enable or disable tcp_nodelay for inter-dc communication.
|
||||
# Disabling it will result in larger (but fewer) network packets being sent,
|
||||
# reducing overhead from the TCP protocol itself, at the cost of increasing
|
||||
# latency if you block for cross-datacenter responses.
|
||||
inter_dc_tcp_nodelay: false
|
||||
|
||||
# Enable or disable kernel page cache preheating from contents of the key cache after compaction.
|
||||
# When enabled it would preheat only first "page" (4KB) of each row to optimize
|
||||
# for sequential access. Note: This could be harmful for fat rows, see CASSANDRA-4937
|
||||
# for further details on that topic.
|
||||
preheat_kernel_page_cache: false
|
||||
23
test-support/get-and-start-cassandra
Executable file
23
test-support/get-and-start-cassandra
Executable file
@@ -0,0 +1,23 @@
|
||||
CASSANDRA_DIST=.cassandra/dist
|
||||
mkdir -p $CASSANDRA_DIST
|
||||
|
||||
curl -sL http://downloads.datastax.com/community/dsc.tar.gz > $CASSANDRA_DIST/dist.tgz
|
||||
tar -xzf $CASSANDRA_DIST/dist.tgz -C $CASSANDRA_DIST
|
||||
|
||||
CASSANDRA_HOME=`find $CASSANDRA_DIST -name 'dsc-cassandra-*' -print`
|
||||
if [ -z "$CASSANDRA_HOME" ]; then
|
||||
echo "Couldn't determine CASSANDRA_HOME"
|
||||
exit 1
|
||||
fi
|
||||
echo "CASSANDRA_HOME is $CASSANDRA_HOME"
|
||||
|
||||
# these directories must match what's in test-support/cassandra/conf/cassandra.yaml
|
||||
mkdir -p .cassandra/var/lib/cassandra
|
||||
mkdir -p .cassandra/var/log/cassandra
|
||||
|
||||
mv $CASSANDRA_HOME/conf/cassandra.yaml $CASSANDRA_HOME/conf/cassandra.yaml.original
|
||||
cp test-support/cassandra/conf/cassandra.yaml $CASSANDRA_HOME/conf/cassandra.yaml
|
||||
|
||||
$CASSANDRA_HOME/bin/cassandra -p $CASSANDRA_HOME/cassandra.pid
|
||||
|
||||
sleep 5
|
||||
Reference in New Issue
Block a user