Permalink
Browse files

dynamodb plugin for Amazon AWS DynamoDB: initial version

  • Loading branch information...
1 parent af8d91b commit 394903be0ef4455f1c6e2bd4e64e9350bd39f7e8 @rstepanenko rstepanenko committed Apr 13, 2012
Showing with 9,724 additions and 0 deletions.
  1. +6 −0 grails-datastore-dynamodb/build.gradle
  2. +43 −0 ...ynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/DelayAfterWriteDynamoDBSession.java
  3. +233 −0 ...s-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/DynamoDBDatastore.java
  4. +81 −0 grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/DynamoDBSession.java
  5. +96 −0 ...b/src/main/groovy/org/grails/datastore/mapping/dynamodb/config/DynamoDBDomainClassMappedForm.java
  6. +64 −0 ...dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/config/DynamoDBMappingContext.java
  7. +48 −0 ...namodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/config/DynamoDBPersistentEntity.java
  8. +58 −0 ...modb/src/main/groovy/org/grails/datastore/mapping/dynamodb/config/GormDynamoDBMappingFactory.java
  9. +39 −0 ...b/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/AbstractDynamoDBTableResolver.java
  10. +62 −0 ...tastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/AssociationKey.java
  11. +42 −0 ...modb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/ConstDynamoDBTableResolver.java
  12. +116 −0 ...modb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBAssociationIndexer.java
  13. +39 −0 ...ynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBAssociationInfo.java
  14. +279 −0 ...ynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBEntityPersister.java
  15. +148 −0 ...ynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBHiLoIdGenerator.java
  16. +12 −0 ...re-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBIdGenerator.java
  17. +63 −0 ...modb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBIdGeneratorFactory.java
  18. +74 −0 ...ore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBNativeItem.java
  19. +48 −0 ...-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBTableResolver.java
  20. +41 −0 ...db/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBTableResolverFactory.java
  21. +15 −0 ...ynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBUUIDIdGenerator.java
  22. +34 −0 ...main/groovy/org/grails/datastore/mapping/dynamodb/model/types/DynamoDBTypeConverterRegistrar.java
  23. +553 −0 ...datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/query/DynamoDBQuery.java
  24. +11 −0 ...amodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DataStoreOperationException.java
  25. +116 −0 ...n/groovy/org/grails/datastore/mapping/dynamodb/util/DelayAfterWriteDynamoDBTemplateDecorator.java
  26. +55 −0 ...-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DynamoDBConst.java
  27. +45 −0 ...re-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DynamoDBConverterUtil.java
  28. +158 −0 ...tastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DynamoDBTemplate.java
  29. +458 −0 ...ore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DynamoDBTemplateImpl.java
  30. +281 −0 ...s-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DynamoDBUtil.java
  31. +38 −0 grails-datastore-gorm-dynamodb/build.gradle
  32. +36 −0 ...ore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/DynamoDBCriteriaBuilder.java
  33. +126 −0 ...tore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/DynamoDBGormEnhancer.groovy
  34. +57 −0 ...c/main/groovy/org/grails/datastore/gorm/dynamodb/bean/factory/DynamoDBDatastoreFactoryBean.groovy
  35. +18 −0 ...n/groovy/org/grails/datastore/gorm/dynamodb/bean/factory/DynamoDBMappingContextFactoryBean.groovy
  36. +186 −0 ...ovy/org/grails/datastore/gorm/dynamodb/plugin/support/DynamoDBApplicationContextConfigurer.groovy
  37. +65 −0 ...rc/main/groovy/org/grails/datastore/gorm/dynamodb/plugin/support/DynamoDBMethodsConfigurer.groovy
  38. +34 −0 .../src/main/groovy/org/grails/datastore/gorm/dynamodb/plugin/support/DynamoDBOnChangeHandler.groovy
  39. +64 −0 ...src/main/groovy/org/grails/datastore/gorm/dynamodb/plugin/support/DynamoDBSpringConfigurer.groovy
  40. +18 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Book.groovy
  41. +25 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ChildEntity.groovy
  42. +18 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/City.groovy
  43. +29 −0 ...s-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ClassWithListArgBeforeValidate.groovy
  44. +27 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ClassWithNoArgBeforeValidate.groovy
  45. +32 −0 ...atastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ClassWithOverloadedBeforeValidate.groovy
  46. +57 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/CommonTypes.groovy
  47. +20 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ConstrainedEntity.groovy
  48. +29 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Country.groovy
  49. +158 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/CriteriaBuilderSpec.groovy
  50. +244 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/DetachedCriteriaSpec.groovy
  51. +61 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/DynamoDBCombinationSpec.groovy
  52. +18 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/EnumThing.groovy
  53. +11 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Face.groovy
  54. +32 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/GroupWithin.groovy
  55. +19 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Highway.groovy
  56. +75 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/InheritanceSpec.groovy
  57. +371 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/LexComparisonSpec.groovy
  58. +23 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Location.groovy
  59. +22 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ModifyPerson.groovy
  60. +31 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/MultilineValueSpec.groovy
  61. +67 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/NegationSpec.groovy
  62. +11 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Nose.groovy
  63. +21 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/OptLockNotVersioned.groovy
  64. +17 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/OptLockVersioned.groovy
  65. +57 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PagedResultSpec.groovy
  66. +31 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Person.groovy
  67. +66 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PersonEvent.groovy
  68. +36 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Pet.groovy
  69. +20 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PetType.groovy
  70. +18 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Plant.groovy
  71. +20 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PlantCategory.groovy
  72. +31 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PlantNumericIdValue.groovy
  73. +14 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PropertyComparisonQuerySpec.groovy
  74. +87 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Publication.groovy
  75. +36 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/SimpleDBHiloSpec.groovy
  76. +15 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy
  77. +26 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Task.groovy
  78. +42 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/TestEntity.groovy
  79. +29 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/UniqueGroup.groovy
  80. +180 −0 grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ValidationSpec.groovy
  81. +168 −0 grails-datastore-gorm-dynamodb/src/test/groovy/org/grails/datastore/gorm/Setup.groovy
  82. +3 −0 grails-documentation-dynamodb/build.gradle
  83. +4 −0 grails-documentation-dynamodb/src/docs/doc.properties
  84. +6 −0 grails-documentation-dynamodb/src/docs/guide/gettingStarted.gdoc
  85. +83 −0 grails-documentation-dynamodb/src/docs/guide/gettingStarted/configurationOptions.gdoc
  86. +21 −0 grails-documentation-dynamodb/src/docs/guide/introduction.gdoc
  87. +38 −0 grails-documentation-dynamodb/src/docs/guide/introduction/currentFeatureSet.gdoc
  88. +50 −0 grails-documentation-dynamodb/src/docs/guide/introduction/dynamoDBSpecifics.gdoc
  89. +83 −0 grails-documentation-dynamodb/src/docs/guide/mapping.gdoc
  90. +29 −0 grails-documentation-dynamodb/src/docs/guide/mapping/identityGeneration.gdoc
  91. +17 −0 grails-documentation-dynamodb/src/docs/guide/mapping/provisionedThroughput.gdoc
  92. +13 −0 grails-documentation-dynamodb/src/docs/guide/releaseNotes.gdoc
  93. +13 −0 grails-documentation-dynamodb/src/docs/guide/toc.yml
  94. +29 −0 grails-documentation-dynamodb/src/docs/guide/transactions.gdoc
  95. +5 −0 grails-plugins/dynamodb/application.properties
  96. +59 −0 grails-plugins/dynamodb/grails-app/conf/BuildConfig.groovy
  97. +24 −0 grails-plugins/dynamodb/grails-app/conf/Config.groovy
  98. +32 −0 grails-plugins/dynamodb/grails-app/conf/DataSource.groovy
  99. 0 grails-plugins/dynamodb/grails-app/i18n/messages.properties
  100. +10 −0 grails-plugins/dynamodb/scripts/_Install.groovy
  101. +5 −0 grails-plugins/dynamodb/scripts/_Uninstall.groovy
  102. +10 −0 grails-plugins/dynamodb/scripts/_Upgrade.groovy
  103. +33 −0 grails-plugins/dynamodb/web-app/WEB-INF/applicationContext.xml
  104. +14 −0 grails-plugins/dynamodb/web-app/WEB-INF/sitemesh.xml
  105. +572 −0 grails-plugins/dynamodb/web-app/WEB-INF/tld/c.tld
  106. +671 −0 grails-plugins/dynamodb/web-app/WEB-INF/tld/fmt.tld
  107. +550 −0 grails-plugins/dynamodb/web-app/WEB-INF/tld/grails.tld
  108. +311 −0 grails-plugins/dynamodb/web-app/WEB-INF/tld/spring.tld
  109. +109 −0 grails-plugins/dynamodb/web-app/css/errors.css
  110. +585 −0 grails-plugins/dynamodb/web-app/css/main.css
  111. +82 −0 grails-plugins/dynamodb/web-app/css/mobile.css
  112. BIN grails-plugins/dynamodb/web-app/images/apple-touch-icon-retina.png
  113. BIN grails-plugins/dynamodb/web-app/images/apple-touch-icon.png
  114. BIN grails-plugins/dynamodb/web-app/images/favicon.ico
  115. BIN grails-plugins/dynamodb/web-app/images/grails_logo.jpg
  116. BIN grails-plugins/dynamodb/web-app/images/grails_logo.png
  117. BIN grails-plugins/dynamodb/web-app/images/leftnav_btm.png
  118. BIN grails-plugins/dynamodb/web-app/images/leftnav_midstretch.png
  119. BIN grails-plugins/dynamodb/web-app/images/leftnav_top.png
  120. BIN grails-plugins/dynamodb/web-app/images/skin/database_add.png
  121. BIN grails-plugins/dynamodb/web-app/images/skin/database_delete.png
  122. BIN grails-plugins/dynamodb/web-app/images/skin/database_edit.png
  123. BIN grails-plugins/dynamodb/web-app/images/skin/database_save.png
  124. BIN grails-plugins/dynamodb/web-app/images/skin/database_table.png
  125. BIN grails-plugins/dynamodb/web-app/images/skin/exclamation.png
  126. BIN grails-plugins/dynamodb/web-app/images/skin/house.png
  127. BIN grails-plugins/dynamodb/web-app/images/skin/information.png
  128. BIN grails-plugins/dynamodb/web-app/images/skin/shadow.jpg
  129. BIN grails-plugins/dynamodb/web-app/images/skin/sorted_asc.gif
  130. BIN grails-plugins/dynamodb/web-app/images/skin/sorted_desc.gif
  131. BIN grails-plugins/dynamodb/web-app/images/spinner.gif
  132. BIN grails-plugins/dynamodb/web-app/images/springsource.png
  133. +9 −0 grails-plugins/dynamodb/web-app/js/application.js
@@ -0,0 +1,6 @@
+version = "0.1.BUILD-SNAPSHOT"
+
+dependencies {
+ compile project(":grails-datastore-core")
+ compile('com.amazonaws:aws-java-sdk:1.3.3')
+}
@@ -0,0 +1,43 @@
+/* Copyright (C) 2011 SpringSource
+ *
+ * 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.grails.datastore.mapping.dynamodb;
+
+import org.grails.datastore.mapping.cache.TPCacheAdapterRepository;
+import org.grails.datastore.mapping.model.MappingContext;
+import org.springframework.context.ApplicationEventPublisher;
+
+/**
+ * Simple extension used in testing to fight eventual consistency of DynamoDB.
+ */
+public class DelayAfterWriteDynamoDBSession extends DynamoDBSession {
+
+ private long delayMillis;
+
+ public DelayAfterWriteDynamoDBSession(DynamoDBDatastore datastore, MappingContext mappingContext, ApplicationEventPublisher publisher, long delayMillis, TPCacheAdapterRepository cacheAdapterRepository) {
+ super(datastore, mappingContext, publisher, cacheAdapterRepository);
+ this.delayMillis = delayMillis;
+ }
+
+ @Override
+ protected void postFlush(boolean hasUpdates) {
+ if (hasUpdates) {
+ pause();
+ }
+ }
+
+ private void pause(){
+ try { Thread.sleep(delayMillis); } catch (InterruptedException e) { /* ignored */ }
+ }
+}
@@ -0,0 +1,233 @@
+/* Copyright (C) 2011 SpringSource
+ *
+ * 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.grails.datastore.mapping.dynamodb;
+
+import org.grails.datastore.mapping.cache.TPCacheAdapterRepository;
+import org.grails.datastore.mapping.core.AbstractDatastore;
+import org.grails.datastore.mapping.core.Session;
+import org.grails.datastore.mapping.dynamodb.engine.*;
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.types.Association;
+import org.grails.datastore.mapping.model.types.OneToMany;
+import org.grails.datastore.mapping.dynamodb.config.DynamoDBMappingContext;
+import org.grails.datastore.mapping.dynamodb.model.types.DynamoDBTypeConverterRegistrar;
+import org.grails.datastore.mapping.dynamodb.util.DelayAfterWriteDynamoDBTemplateDecorator;
+import org.grails.datastore.mapping.dynamodb.util.DynamoDBTemplate;
+import org.grails.datastore.mapping.dynamodb.util.DynamoDBTemplateImpl;
+import org.grails.datastore.mapping.dynamodb.util.DynamoDBUtil;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.convert.converter.ConverterRegistry;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.grails.datastore.mapping.config.utils.ConfigUtils.read;
+
+/**
+ * A Datastore implementation for the AWS DynamoDB document store.
+ *
+ * @author Roman Stepanenko based on Graeme Rocher code for MongoDb and Redis
+ * @since 0.1
+ */
+public class DynamoDBDatastore extends AbstractDatastore implements InitializingBean, MappingContext.Listener {
+
+ public static final String SECRET_KEY = "secretKey";
+ public static final String ACCESS_KEY = "accessKey";
+ public static final String TABLE_NAME_PREFIX_KEY = "tableNamePrefix";
+ public static final String DEFAULT_READ_CAPACITY_UNITS = "defaultReadCapacityUnits";
+ public static final String DEFAULT_WRITE_CAPACITY_UNITS = "defaultWriteCapacityUnits";
+ public static final String DELAY_AFTER_WRITES_MS = "delayAfterWritesMS"; //used for testing - to fight eventual consistency if this flag value is 'true' it will add specified pause after writes
+
+ private DynamoDBTemplate dynamoDBTemplate; //currently there is no need to create template per entity, we can share same instance
+ protected Map<AssociationKey, DynamoDBAssociationInfo> associationInfoMap = new HashMap<AssociationKey, DynamoDBAssociationInfo>(); //contains entries only for those associations that need a dedicated table
+ protected Map<PersistentEntity, DynamoDBTableResolver> entityDomainResolverMap = new HashMap<PersistentEntity, DynamoDBTableResolver>();
+ protected Map<PersistentEntity, DynamoDBIdGenerator> entityIdGeneratorMap = new HashMap<PersistentEntity, DynamoDBIdGenerator>();
+
+ private String tableNamePrefix;
+
+ private long defaultReadCapacityUnits;
+ private long defaultWriteCapacityUnits;
+
+ public DynamoDBDatastore() {
+ this(new DynamoDBMappingContext(), Collections.<String, String>emptyMap(), null, null);
+ }
+
+ /**
+ * Constructs a DynamoDBDatastore using the given MappingContext and connection details map.
+ *
+ * @param mappingContext The DynamoDBMappingContext
+ * @param connectionDetails The connection details containing the {@link #ACCESS_KEY} and {@link #SECRET_KEY} settings
+ */
+ public DynamoDBDatastore(MappingContext mappingContext,
+ Map<String, String> connectionDetails, ConfigurableApplicationContext ctx, TPCacheAdapterRepository<DynamoDBNativeItem> adapterRepository) {
+ super(mappingContext, connectionDetails, ctx, adapterRepository);
+
+ if (mappingContext != null) {
+ mappingContext.addMappingContextListener(this);
+ }
+
+ initializeConverters(mappingContext);
+
+ tableNamePrefix = read(String.class, TABLE_NAME_PREFIX_KEY, connectionDetails, null);
+ defaultReadCapacityUnits = read(Long.class, DEFAULT_READ_CAPACITY_UNITS, connectionDetails, (long)3); //minimum for the account in us-east-1 is 3
+ defaultWriteCapacityUnits = read(Long.class, DEFAULT_WRITE_CAPACITY_UNITS, connectionDetails, (long)5); //minimum for the account in us-east-1 is 5
+ }
+
+ public DynamoDBDatastore(MappingContext mappingContext, Map<String, String> connectionDetails) {
+ this(mappingContext, connectionDetails, null, null);
+ }
+
+ public DynamoDBDatastore(MappingContext mappingContext) {
+ this(mappingContext, Collections.<String, String>emptyMap(), null, null);
+ }
+
+ public DynamoDBTemplate getDynamoDBTemplate(@SuppressWarnings("unused") PersistentEntity entity) {
+// return dynamoDBTemplates.get(entity);
+ return dynamoDBTemplate;
+ }
+
+ public DynamoDBTemplate getDynamoDBTemplate() {
+ return dynamoDBTemplate;
+ }
+
+ @Override
+ protected Session createSession(Map<String, String> connDetails) {
+ String delayAfterWrite = read(String.class, DELAY_AFTER_WRITES_MS, connectionDetails, null);
+
+ if (delayAfterWrite != null && !"".equals(delayAfterWrite)) {
+ return new DelayAfterWriteDynamoDBSession(this, getMappingContext(), getApplicationEventPublisher(), Integer.parseInt(delayAfterWrite), cacheAdapterRepository);
+ }
+ return new DynamoDBSession(this, getMappingContext(), getApplicationEventPublisher(), cacheAdapterRepository);
+ }
+
+ public void afterPropertiesSet() throws Exception {
+// for (PersistentEntity entity : mappingContext.getPersistentEntities()) {
+ // Only create DynamoDB templates for entities that are mapped with DynamoDB
+// if (!entity.isExternal()) {
+// createDynamoDBTemplate(entity);
+// }
+// }
+ createDynamoDBTemplate();
+}
+
+ protected void createDynamoDBTemplate() {
+ if (dynamoDBTemplate != null) {
+ return;
+ }
+
+ String accessKey = read(String.class, ACCESS_KEY, connectionDetails, null);
+ String secretKey = read(String.class, SECRET_KEY, connectionDetails, null);
+ String delayAfterWrite = read(String.class, DELAY_AFTER_WRITES_MS, connectionDetails, null);
+
+ dynamoDBTemplate = new DynamoDBTemplateImpl(accessKey, secretKey);
+ if (delayAfterWrite != null && !"".equals(delayAfterWrite)) {
+ dynamoDBTemplate = new DelayAfterWriteDynamoDBTemplateDecorator(dynamoDBTemplate, Integer.parseInt(delayAfterWrite));
+ }
+ }
+
+ /**
+ * If specified, returns table name prefix so that same AWS account can be used for more than one environment (DEV/TEST/PROD etc).
+ * @return null if name was not specified in the configuration
+ */
+ public String getTableNamePrefix() {
+ return tableNamePrefix;
+ }
+
+ public long getDefaultWriteCapacityUnits() {
+ return defaultWriteCapacityUnits;
+ }
+
+ public long getDefaultReadCapacityUnits() {
+ return defaultReadCapacityUnits;
+ }
+
+ public void persistentEntityAdded(PersistentEntity entity) {
+ createDynamoDBTemplate();
+ analyzeAssociations(entity);
+ createEntityDomainResolver(entity);
+ createEntityIdGenerator(entity);
+ }
+
+ /**
+ * If the specified association has a dedicated AWS table, returns info for that association,
+ * otherwise returns null.
+ */
+ public DynamoDBAssociationInfo getAssociationInfo(Association<?> association) {
+ return associationInfoMap.get(generateAssociationKey(association));
+ }
+
+ /**
+ * Returns table resolver for the specified entity.
+ * @param entity
+ * @return
+ */
+ public DynamoDBTableResolver getEntityDomainResolver(PersistentEntity entity) {
+ return entityDomainResolverMap.get(entity);
+ }
+
+ /**
+ * Returns id generator for the specified entity.
+ * @param entity
+ * @return
+ */
+ public DynamoDBIdGenerator getEntityIdGenerator(PersistentEntity entity) {
+ return entityIdGeneratorMap.get(entity);
+ }
+
+ protected void createEntityDomainResolver(PersistentEntity entity) {
+ DynamoDBTableResolverFactory resolverFactory = new DynamoDBTableResolverFactory();
+ DynamoDBTableResolver tableResolver = resolverFactory.buildResolver(entity, this);
+
+ entityDomainResolverMap.put(entity, tableResolver);
+ }
+
+ protected void createEntityIdGenerator(PersistentEntity entity) {
+ DynamoDBIdGeneratorFactory factory = new DynamoDBIdGeneratorFactory();
+ DynamoDBIdGenerator generator = factory.buildIdGenerator(entity, this);
+
+ entityIdGeneratorMap.put(entity, generator);
+ }
+
+ @Override
+ protected void initializeConverters(@SuppressWarnings("hiding") MappingContext mappingContext) {
+ final ConverterRegistry conversionService = mappingContext.getConverterRegistry();
+ new DynamoDBTypeConverterRegistrar().register(conversionService);
+ }
+
+ /**
+ * Analyzes associations and for those associations that need to be stored
+ * in a dedicated AWS table, creates info object with details for that association.
+ */
+ protected void analyzeAssociations(PersistentEntity entity) {
+ for (Association<?> association : entity.getAssociations()) {
+ if (association instanceof OneToMany && !association.isBidirectional()) {
+ String associationDomainName = generateAssociationDomainName(association);
+ associationInfoMap.put(generateAssociationKey(association), new DynamoDBAssociationInfo(associationDomainName));
+ }
+ }
+ }
+
+ protected AssociationKey generateAssociationKey(Association<?> association) {
+ return new AssociationKey(association.getOwner(), association.getName());
+ }
+
+ protected String generateAssociationDomainName(Association<?> association) {
+ String ownerDomainName = DynamoDBUtil.getMappedTableName(association.getOwner());
+ return DynamoDBUtil.getPrefixedTableName(tableNamePrefix, ownerDomainName.toUpperCase() + "_" + association.getName().toUpperCase());
+ }
+}
@@ -0,0 +1,81 @@
+/* Copyright (C) 2011 SpringSource
+ *
+ * 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.grails.datastore.mapping.dynamodb;
+
+import org.grails.datastore.mapping.cache.TPCacheAdapterRepository;
+import org.grails.datastore.mapping.core.AbstractSession;
+import org.grails.datastore.mapping.engine.Persister;
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.dynamodb.engine.DynamoDBEntityPersister;
+import org.grails.datastore.mapping.dynamodb.query.DynamoDBQuery;
+import org.grails.datastore.mapping.dynamodb.util.DynamoDBTemplate;
+import org.grails.datastore.mapping.transactions.SessionOnlyTransaction;
+import org.grails.datastore.mapping.transactions.Transaction;
+import org.springframework.context.ApplicationEventPublisher;
+
+/**
+ * A {@link org.grails.datastore.mapping.core.Session} implementation
+ * for the AWS DynamoDB store.
+ *
+ * @author Roman Stepanenko based on Graeme Rocher code for MongoDb and Redis
+ * @since 0.1
+ */
+public class DynamoDBSession extends AbstractSession {
+
+ DynamoDBDatastore dynamoDBDatastore;
+
+ public DynamoDBSession(DynamoDBDatastore datastore, MappingContext mappingContext, ApplicationEventPublisher publisher, TPCacheAdapterRepository cacheAdapterRepository) {
+ super(datastore, mappingContext, publisher, cacheAdapterRepository);
+ this.dynamoDBDatastore = datastore;
+ }
+
+ @Override
+ public DynamoDBQuery createQuery(@SuppressWarnings("rawtypes") Class type) {
+ return (DynamoDBQuery) super.createQuery(type);
+ }
+
+/* @Override
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ protected void flushPendingInserts(Map<PersistentEntity, Collection<PendingInsert>> inserts) {
+ //todo - optimize multiple inserts using batch put (make the number of threshold objects configurable)
+ for (final PersistentEntity entity : inserts.keySet()) {
+ final DynamoDBTemplate template = getDynamoDBTemplate(entity.isRoot() ? entity : entity.getRootEntity());
+
+ throw new RuntimeException("not implemented yet");
+// template.persist(null); //todo - :)
+ }
+ }
+ */
+
+ public Object getNativeInterface() {
+ return null; //todo
+ }
+
+ @Override
+ protected Persister createPersister(@SuppressWarnings("rawtypes") Class cls, MappingContext mappingContext) {
+ final PersistentEntity entity = mappingContext.getPersistentEntity(cls.getName());
+ return entity == null ? null : new DynamoDBEntityPersister(mappingContext, entity, this, publisher, cacheAdapterRepository);
+ }
+
+ @Override
+ protected Transaction beginTransactionInternal() {
+ return new SessionOnlyTransaction(null, this);
+ }
+
+ public DynamoDBTemplate getDynamoDBTemplate() {
+ return dynamoDBDatastore.getDynamoDBTemplate();
+ }
+}
Oops, something went wrong. Retry.

0 comments on commit 394903b

Please sign in to comment.