You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polygene.apache.org by ni...@apache.org on 2017/02/19 07:17:54 UTC
polygene-java git commit: Adding more flexible configuration and more
documentation.
Repository: polygene-java
Updated Branches:
refs/heads/develop 829168ddc -> ba600a555
Adding more flexible configuration and more documentation.
Project: http://git-wip-us.apache.org/repos/asf/polygene-java/repo
Commit: http://git-wip-us.apache.org/repos/asf/polygene-java/commit/ba600a55
Tree: http://git-wip-us.apache.org/repos/asf/polygene-java/tree/ba600a55
Diff: http://git-wip-us.apache.org/repos/asf/polygene-java/diff/ba600a55
Branch: refs/heads/develop
Commit: ba600a55520dee34a78e3e056ae1faf89355aba8
Parents: 829168d
Author: niclas <ni...@spicter.com>
Authored: Sun Feb 19 15:17:38 2017 +0800
Committer: niclas <ni...@spicter.com>
Committed: Sun Feb 19 15:17:38 2017 +0800
----------------------------------------------------------------------
.../src/docs/es-cassandra.txt | 116 +++++++++++++++++++
.../entitystore/cassandra/CassandraCluster.java | 38 +++---
.../CassandraEntityStoreConfiguration.java | 7 ++
.../cassandra/CassandraEntityStoreMixin.java | 42 ++++---
.../entitystore/cassandra/ClusterBuilder.java | 105 +++++++++++++++++
.../polygene/entitystore/cassandra/package.html | 48 ++++++--
.../entitystore/cassandra/DocSupport.java | 68 +++++++++++
7 files changed, 384 insertions(+), 40 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/ba600a55/extensions/entitystore-cassandra/src/docs/es-cassandra.txt
----------------------------------------------------------------------
diff --git a/extensions/entitystore-cassandra/src/docs/es-cassandra.txt b/extensions/entitystore-cassandra/src/docs/es-cassandra.txt
new file mode 100644
index 0000000..25da991
--- /dev/null
+++ b/extensions/entitystore-cassandra/src/docs/es-cassandra.txt
@@ -0,0 +1,116 @@
+///////////////////////////////////////////////////////////////
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+///////////////////////////////////////////////////////////////
+
+[[extension-es-cassandra,Cassandra EntityStore]]
+= Cassandra EntityStore =
+
+[devstatus]
+--------------
+source=extensions/entitystore-cassandra/dev-status.xml
+--------------
+
+EntityStore service backed by a http://cassandra.apache.org/ in which Entity state is stored in single rows of a
+single table.
+
+include::../../build/docs/buildinfo/artifact.txt[]
+
+== Assembly ==
+
+Assembly is done using the provided Assembler:
+
+[snippet,java]
+----
+source=extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/CassandraMapEntityStoreTest.java
+tag=assembly
+----
+
+=== Custom Cluster Client ===
+There are many options in Apache Cassandra on how the cluster is set up and how to connect to it. Instead of mapping
+all possible features, a ClusterBuilder type, which by default sets it up according to this page. By overriding the
+DefaultBuilder mixin, on the CassandraCluster composite, it is possible to provide your configuration.
+
+[snippet,java]
+----
+source=extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/DocSupport.java
+tag=assembly
+----
+
+And we then have a choice to override any of the provided extension points in DefaultBuilder. For instance;
+
+[snippet,java]
+----
+source=extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/DocSupport.java
+tag=builder
+----
+
+Of course, it is possible to simply override the entire Mixin and not subtype it at all.
+
+== Configuration ==
+
+Here are the configuration properties for the Cassandra EntityStore:
+
+[snippet,java]
+----
+source=extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreConfiguration.java
+tag=config
+----
+
+== Cassandra Authentication ==
+It is possible to configure Cassandra with many types of authentication. User/password is provided in this library's
+configuration, and for more advanced setups, you need to provide an implementation of com.datastax.driver.core.AuthProvider
+as a Polygene service (and visible to the ClusterBuilder as usual).
+
+== Cassandra Keyspace ==
+The Cassandra EntityStore can either use an existing Cassandra Keyspace, which is the default, OR create its own
+keyspace.
+
+The CassandraEntityStoreConfiguration#keyspaceName() defines the name of the keyspace to use, or to be created. If not
+defined, then the default name is "polygene".
+
+The CassandraEntityStoreConfiguration#createIfMissing() defines if new missing resources should be created or an
+Exception should be thrown if missing.
+
+If the keyspace is created, then the CassandraEntityStoreConfiguration#replicationFactor() will define the replication
+factor, defaults to 3, and the command to create the keyspace is;
+
+[source]
+-----------------
+ CREATE KEYSPACE <keyspaceName> WITH replication = {'class':'SimpleStrategy', 'replication_factor' : <replicationFactor> };
+-----------------
+
+== Polygene's Cassandra Table ==
+
+Polygene will store all entities in a single Cassandra TABLE
+
+[source]
+-----------------
+ CREATE TABLE <tableName> (
+ id text,
+ version text,
+ appversion text,
+ storeversion text,
+ usecase text,
+ modified timestamp,
+ properties map<string,string>
+ assocs map<string,string>
+ manyassocs map<string,string>
+ namedassocs map<string,string>
+ PRIMARY KEY ( id )
+ );
+-----------------
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/ba600a55/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraCluster.java
----------------------------------------------------------------------
diff --git a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraCluster.java b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraCluster.java
index a8d3d29..701471c 100644
--- a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraCluster.java
+++ b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraCluster.java
@@ -38,14 +38,16 @@
*/
package org.apache.polygene.entitystore.cassandra;
+import com.datastax.driver.core.AuthProvider;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.KeyspaceMetadata;
import com.datastax.driver.core.PreparedStatement;
import com.datastax.driver.core.Session;
+import org.apache.polygene.api.common.Optional;
import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.Service;
import org.apache.polygene.api.injection.scope.This;
import org.apache.polygene.api.mixin.Mixins;
-import org.apache.polygene.api.service.ServiceActivation;
import org.apache.polygene.spi.entitystore.EntityStoreException;
@Mixins( CassandraCluster.Mixin.class )
@@ -55,11 +57,11 @@ public interface CassandraCluster
String DEFAULT_KEYSPACE_NAME = "polygene";
String DEFAULT_TABLE_NAME = "entitystore";
String IDENTITY_COLUMN = "id";
+ String STORE_VERSION_COLUMN = "storeversion";
String VERSION_COLUMN = "version";
+ String APP_VERSION_COLUMN = "appversion";
String USECASE_COLUMN = "usecase";
String LASTMODIFIED_COLUMN = "modified";
- String APP_VERSION_COLUMN = "appversion";
- String STORE_VERSION_COLUMN = "storeversion";
String TYPE_COLUMN = "type";
String PROPERTIES_COLUMN = "props";
String ASSOCIATIONS_COLUMN = "assocs";
@@ -78,12 +80,25 @@ public interface CassandraCluster
String keyspaceName();
+ void activate()
+ throws Exception;
+
+ void passivate()
+ throws Exception;
+
class Mixin
- implements ServiceActivation, CassandraCluster
+ implements CassandraCluster
{
@This
private Configuration<CassandraEntityStoreConfiguration> configuration;
+ @Service
+ @Optional
+ private AuthProvider authProvider;
+
+ @This
+ private ClusterBuilder clusterBuilder;
+
private Cluster cluster;
private Session session;
private String keyspaceName;
@@ -132,20 +147,12 @@ public interface CassandraCluster
return tableName;
}
- @Override
- public void activateService()
+ public void activate()
throws Exception
{
configuration.refresh();
CassandraEntityStoreConfiguration config = configuration.get();
-
- String[] hostNames = config.hostnames().get().split( "," );
- Cluster.Builder builder =
- Cluster.builder()
- .withClusterName( "myCluster" )
- .addContactPoints( hostNames )
- .withCredentials( config.username().get(), config.password().get() );
- cluster = builder.build();
+ cluster = clusterBuilder.build(config);
keyspaceName = config.keySpace().get();
if( keyspaceName == null )
{
@@ -233,8 +240,7 @@ public interface CassandraCluster
}
}
- @Override
- public void passivateService()
+ public void passivate()
throws Exception
{
cluster.close();
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/ba600a55/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreConfiguration.java
----------------------------------------------------------------------
diff --git a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreConfiguration.java b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreConfiguration.java
index f0ab16e..f212d78 100644
--- a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreConfiguration.java
+++ b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreConfiguration.java
@@ -43,6 +43,13 @@ public interface CassandraEntityStoreConfiguration
@Optional
Property<String> hostnames();
+ /** The name of the cluster to connect to.
+ *
+ * @return The configured cluster name. Default: "polygene-cluster"
+ */
+ @Optional
+ Property<String> clusterName();
+
/** The replication factor to be used, if a KEYSPACE is created.
*
* @return The replication factor to use in the keyspace if a keyspace is created. Default: 3
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/ba600a55/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreMixin.java
----------------------------------------------------------------------
diff --git a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreMixin.java b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreMixin.java
index 159bc9c..798b63b 100644
--- a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreMixin.java
+++ b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreMixin.java
@@ -22,6 +22,7 @@ package org.apache.polygene.entitystore.cassandra;
import com.datastax.driver.core.BoundStatement;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
+import com.datastax.driver.core.Session;
import com.datastax.driver.core.TypeTokens;
import com.google.common.reflect.TypeToken;
import java.time.Instant;
@@ -83,7 +84,7 @@ import static org.apache.polygene.entitystore.cassandra.CassandraCluster.VERSION
* MongoDB implementation of MapEntityStore.
*/
public class CassandraEntityStoreMixin
- implements EntityStore, EntityStoreSPI
+ implements EntityStore, EntityStoreSPI, ServiceActivation
{
@This
@@ -407,19 +408,34 @@ public class CassandraEntityStoreMixin
@Override
public Stream<EntityState> entityStates( ModuleDescriptor module )
{
- ResultSet resultSet = cluster.session().execute( "SELECT "
- + IDENTITY_COLUMN + ", "
- + VERSION_COLUMN + ", "
- + APP_VERSION_COLUMN + ", "
- + STORE_VERSION_COLUMN + ", "
- + LASTMODIFIED_COLUMN + ", "
- + USECASE_COLUMN + ", "
- + PROPERTIES_COLUMN + ", "
- + ASSOCIATIONS_COLUMN + ", "
- + MANYASSOCIATIONS_COLUMN + ", "
- + NAMEDASSOCIATIONS_COLUMN
- + " FROM " + cluster.tableName() );
+ Session session = cluster.session();
+ String tableName = cluster.tableName();
+ ResultSet resultSet = session.execute( "SELECT "
+ + IDENTITY_COLUMN + ", "
+ + VERSION_COLUMN + ", "
+ + APP_VERSION_COLUMN + ", "
+ + STORE_VERSION_COLUMN + ", "
+ + LASTMODIFIED_COLUMN + ", "
+ + USECASE_COLUMN + ", "
+ + PROPERTIES_COLUMN + ", "
+ + ASSOCIATIONS_COLUMN + ", "
+ + MANYASSOCIATIONS_COLUMN + ", "
+ + NAMEDASSOCIATIONS_COLUMN
+ + " FROM " + tableName );
return stream(resultSet.spliterator(), false).map( row -> deserialize( row, module ));
}
+ @Override
+ public void activateService()
+ throws Exception
+ {
+ cluster.activate();
+ }
+
+ @Override
+ public void passivateService()
+ throws Exception
+ {
+ cluster.passivate();
+ }
}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/ba600a55/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/ClusterBuilder.java
----------------------------------------------------------------------
diff --git a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/ClusterBuilder.java b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/ClusterBuilder.java
new file mode 100644
index 0000000..df01331
--- /dev/null
+++ b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/ClusterBuilder.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.polygene.entitystore.cassandra;
+
+import com.datastax.driver.core.Cluster;
+import java.net.InetSocketAddress;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.stream.Collectors;
+import org.apache.polygene.api.mixin.Mixins;
+
+@Mixins(ClusterBuilder.DefaultBuilder.class)
+public interface ClusterBuilder
+{
+ String DEFAULT_HOST_PORT = "localhost:9042";
+
+ Cluster build(CassandraEntityStoreConfiguration config);
+
+ class DefaultBuilder
+ implements ClusterBuilder
+ {
+
+ protected CassandraEntityStoreConfiguration config;
+
+ @Override
+ public Cluster build( CassandraEntityStoreConfiguration config )
+ {
+ this.config = config;
+ String clusterName = clusterName( config );
+ Collection<InetSocketAddress> connectionPoints = cassandraConnectionPoints();
+ Cluster.Builder builder =
+ Cluster.builder()
+ .withClusterName( clusterName )
+ .addContactPointsWithPorts(connectionPoints)
+ .withCredentials( username(), password() );
+ builder = customConfiguration(builder);
+ return builder.build();
+ }
+
+ protected String clusterName( CassandraEntityStoreConfiguration config )
+ {
+ String clusterName = config.clusterName().get();
+ if( clusterName == null )
+ {
+ clusterName = "polygene-cluster";
+ }
+ return clusterName;
+ }
+
+ protected String username()
+ {
+ return config.username().get();
+ }
+
+ protected String password()
+ {
+ return config.password().get();
+ }
+
+ protected Collection<InetSocketAddress> cassandraConnectionPoints()
+ {
+ String hostnames = hostnames();
+ return Arrays.stream( hostnames.split( "(,| )" ) )
+ .map( text ->
+ {
+ String[] strings = text.split( ":" );
+ return new InetSocketAddress( strings[ 0 ], Integer.parseInt( strings[ 1 ] ) );
+ }
+ )
+ .collect( Collectors.toList() );
+ }
+
+ protected String hostnames()
+ {
+ String hostnames = config.hostnames().get();
+ if( hostnames == null )
+ {
+ hostnames = DEFAULT_HOST_PORT;
+ }
+ return hostnames;
+ }
+
+ protected Cluster.Builder customConfiguration( Cluster.Builder builder )
+ {
+ return builder;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/ba600a55/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/package.html
----------------------------------------------------------------------
diff --git a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/package.html b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/package.html
index 2a0077e..f5fbec6 100644
--- a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/package.html
+++ b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/package.html
@@ -20,24 +20,50 @@
<html>
<body>
<h2>Casssandra EntityStore.</h2>
- <p>
- The Cassandra EntityStore leverages the CQL 'map' type, which is the "newer" way of doing variable-wdith rows.
- </p>
+<h3>Polygene's Cassandra Keyspace</h3>
<p>
- For properties, there is a map called '_props' with string key (the name of the property) and string value,
- which is the serialized state of the property.
+ The Cassandra EntityStore can either use an existing Cassandra Keyspace, which is the default, OR create its own
+ keyspace.
</p>
<p>
- For associations, there is map called '_assocs' with string key (the name of the association) and string value,
- which is the entity reference in toString() format.
+ The {@code CassandraEntityStoreConfiguration#keyspaceName()} defines the name of the keyspace to use, or to be
+ created.
+ If not defined, then the default name is "polygene".
</p>
<p>
- For manyassociations, there is map called '_manyassocs' with string key (the name of the manyassociation) and
- list of strings value, which is the list of entity references in toString() format.
+ The {@code CassandraEntityStoreConfiguration#createIfMissing()} defines if new missing resources should
+ be created or an Exception should be thrown if missing.
</p>
<p>
- For namedassociations, there is map called '_manyassocs' with string key (the name of the association) and
- map of strings value, which is the name as the key and the value is the entity reference in toString() format.
+ If it is created, then the {@code CassandraEntityStoreConfiguration#replicationFactor()} will define the replication
+ factor, and the command to create the keyspace is;
</p>
+<code>
+ <pre>
+ CREATE KEYSPACE <keyspaceName> WITH replication = {'class':'SimpleStrategy', 'replication_factor' : <replicationFactor> };
+ </pre>
+</code>
+<h3>Polygene's Cassandra Table</h3>
+<p>
+ Polygene will store all entities in a single Cassandra TABLE
+</p>
+<code>
+ <pre>
+ CREATE TABLE <tableName> (
+ id text,
+ version text,
+ appversion text,
+ storeversion text,
+ usecase text,
+ modified timestamp,
+ properties map<string,string>
+ assocs map<string,string>
+ manyassocs map<string,string>
+ namedassocs map<string,string>
+ PRIMARY KEY ( id )
+ );
+ </pre>
+</code>
+
</body>
</html>
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/ba600a55/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/DocSupport.java
----------------------------------------------------------------------
diff --git a/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/DocSupport.java b/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/DocSupport.java
new file mode 100644
index 0000000..e1f281a
--- /dev/null
+++ b/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/DocSupport.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.polygene.entitystore.cassandra;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+
+public class DocSupport
+ implements Assembler
+{
+// START-SNIPPET: assembly
+ @Override
+ public void assemble( ModuleAssembly module )
+ throws AssemblyException
+ {
+// END-SNIPPET: assembly
+ module.services( ClusterBuilder.class ).withMixins( MyClusterBuilder.class );
+// START-SNIPPET: assembly
+ }
+// END-SNIPPET: assembly
+
+// START-SNIPPET: builder
+ public class MyClusterBuilder extends ClusterBuilder.DefaultBuilder
+ implements ClusterBuilder
+ {
+ @Structure
+ private Application application;
+
+ @Override
+ protected String hostnames()
+ {
+ switch( application.mode() )
+ {
+ case development:
+ return "localhost:9042";
+ case staging:
+ return "cassandra.staging:9042";
+ case production:
+ return "cassandra1.prod:9042,cassandra2.prod:9042,cassandra3.prod:9042";
+ case test:
+ default:
+ return "cassandra.test:9042";
+ }
+ }
+ }
+// END-SNIPPET: builder
+}