diff --git a/pom.xml b/pom.xml
index 477fa5f6..fa27ad62 100755
--- a/pom.xml
+++ b/pom.xml
@@ -101,6 +101,11 @@
DynamoDBLocal
[1.11,2.0)
+
+ org.apache.logging.log4j
+ log4j-to-slf4j
+ 2.8.2
+
uk.org.lidalia
@@ -175,7 +180,12 @@
com.amazonaws
DynamoDBLocal
test
-
+
+
+ org.apache.logging.log4j
+ log4j-to-slf4j
+ test
+
junit
junit
@@ -248,6 +258,39 @@
maven-jar-plugin
3.0.2
+
+
+ org.eclipse.m2e
+ lifecycle-mapping
+ 1.0.0
+
+
+
+
+
+
+ net.revelc.code.formatter
+
+
+ formatter-maven-plugin
+
+
+ [2.7.2,)
+
+
+ validate
+
+
+
+
+ true
+
+
+
+
+
+
+
@@ -401,6 +444,7 @@
Max
+ src/spotbugs-exclude.xml
@@ -434,26 +478,6 @@
org.apache.maven.plugins
maven-dependency-plugin
-
-
- unpack-dynamodb-local
-
- unpack
-
- pre-integration-test
-
-
-
- com.jcabi
- DynamoDBLocal
- 2015-07-16
- zip
- ${project.build.directory}/dynamodb-dist
- false
-
-
-
-
copy
@@ -476,60 +500,6 @@
-
- org.codehaus.mojo
- build-helper-maven-plugin
-
-
- reserver-dynamodb-port
-
- reserve-network-port
-
- pre-integration-test
-
-
- dynamodblocal.port
-
-
-
-
-
-
- com.jcabi
- jcabi-dynamodb-maven-plugin
- 0.9.1
-
-
- src/test/resources/user_table.json
- src/test/resources/playlist_table.json
- src/test/resources/feeduser_table.json
- src/test/resources/customerhistory_table.json
- src/test/resources/installation_table.json
- src/test/resources/auditable_user_table.json
-
- ${dynamodblocal.port}
- ${project.build.directory}/dynamodb-dist
-
- -inMemory
-
-
-
-
- pre-integration-test
-
- start
- create-tables
-
-
-
- post-integration-test
-
- stop
-
- post-integration-test
-
-
-
org.apache.maven.plugins
maven-surefire-plugin
diff --git a/src/main/java/org/socialsignin/spring/data/dynamodb/core/DynamoDBTemplate.java b/src/main/java/org/socialsignin/spring/data/dynamodb/core/DynamoDBTemplate.java
index c7ad1d39..f1f47bdf 100644
--- a/src/main/java/org/socialsignin/spring/data/dynamodb/core/DynamoDBTemplate.java
+++ b/src/main/java/org/socialsignin/spring/data/dynamodb/core/DynamoDBTemplate.java
@@ -39,6 +39,7 @@
import org.socialsignin.spring.data.dynamodb.mapping.event.BeforeSaveEvent;
import org.socialsignin.spring.data.dynamodb.mapping.event.DynamoDBMappingEvent;
import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisher;
@@ -57,42 +58,6 @@ public class DynamoDBTemplate implements DynamoDBOperations, ApplicationContextA
private final DynamoDBMapperConfig dynamoDBMapperConfig;
private ApplicationEventPublisher eventPublisher;
- /**
- * Convenient constructor to use the default
- * {@link DynamoDBMapper#DynamoDBMapper(AmazonDynamoDB)}
- *
- * @param amazonDynamoDB
- * The AWS SDK instance to talk to DynamoDB
- * @param dynamoDBMapperConfig
- * The config to use
- */
- public DynamoDBTemplate(AmazonDynamoDB amazonDynamoDB, DynamoDBMapperConfig dynamoDBMapperConfig) {
- this(amazonDynamoDB, dynamoDBMapperConfig, null);
- }
-
- /**
- * Convenient constructor to use the {@link DynamoDBMapperConfig#DEFAULT}
- *
- * @param amazonDynamoDB
- * The AWS SDK instance to talk to DynamoDB
- * @param dynamoDBMapper
- * The Mapper to use
- */
- public DynamoDBTemplate(AmazonDynamoDB amazonDynamoDB, DynamoDBMapper dynamoDBMapper) {
- this(amazonDynamoDB, null, dynamoDBMapper);
- }
-
- /**
- * Convenient construcotr to thse the {@link DynamoDBMapperConfig#DEFAULT} and
- * default {@link DynamoDBMapper#DynamoDBMapper(AmazonDynamoDB)}
- *
- * @param amazonDynamoDB
- * The AWS SDK instance to talk to DynamoDB
- */
- public DynamoDBTemplate(AmazonDynamoDB amazonDynamoDB) {
- this(amazonDynamoDB, null, null);
- }
-
/**
* Initializes a new {@code DynamoDBTemplate}. The following combinations are
* valid:
@@ -106,49 +71,18 @@ public DynamoDBTemplate(AmazonDynamoDB amazonDynamoDB) {
* can be {@code null} -
* {@link DynamoDBMapper#DynamoDBMapper(AmazonDynamoDB, DynamoDBMapperConfig)}
* is used if {@code null} is passed in
+ * @param dynamoDBMapperConfig
*/
- public DynamoDBTemplate(AmazonDynamoDB amazonDynamoDB, DynamoDBMapperConfig dynamoDBMapperConfig,
- DynamoDBMapper dynamoDBMapper) {
+ @Autowired
+ public DynamoDBTemplate(AmazonDynamoDB amazonDynamoDB, DynamoDBMapper dynamoDBMapper,
+ DynamoDBMapperConfig dynamoDBMapperConfig) {
Assert.notNull(amazonDynamoDB, "amazonDynamoDB must not be null!");
- this.amazonDynamoDB = amazonDynamoDB;
+ Assert.notNull(dynamoDBMapper, "dynamoDBMapper must not be null!");
+ Assert.notNull(dynamoDBMapperConfig, "dynamoDBMapperConfig must not be null!");
- if (dynamoDBMapperConfig == null) {
- this.dynamoDBMapperConfig = DynamoDBMapperConfig.DEFAULT;
- } else {
-
- // #146, #81 #157
- // Trying to fix half-initialized DynamoDBMapperConfigs here.
- // The old documentation advised to start with an empty builder. Therefore we
- // try here to set required fields to their defaults -
- // As the documentation at
- // https://github.com/derjust/spring-data-dynamodb/wiki/Alter-table-name-during-runtime
- // (same as https://git.io/DynamoDBMapperConfig)
- // now does: Start with #DEFAULT and add what's required
- DynamoDBMapperConfig.Builder emptyBuilder = DynamoDBMapperConfig.builder(); // empty (!) builder
-
- if (dynamoDBMapperConfig.getConversionSchema() == null) {
- LOGGER.warn(
- "No ConversionSchema set in the provided dynamoDBMapperConfig! Merging with DynamoDBMapperConfig.DEFAULT - Please see https://git.io/DynamoDBMapperConfig");
- // DynamoDBMapperConfig#DEFAULT comes with a ConversionSchema
- emptyBuilder.withConversionSchema(DynamoDBMapperConfig.DEFAULT.getConversionSchema());
- }
-
- if (dynamoDBMapperConfig.getTypeConverterFactory() == null) {
- LOGGER.warn(
- "No TypeConverterFactory set in the provided dynamoDBMapperConfig! Merging with DynamoDBMapperConfig.DEFAULT - Please see https://git.io/DynamoDBMapperConfig");
- // DynamoDBMapperConfig#DEFAULT comes with a TypeConverterFactory
- emptyBuilder.withTypeConverterFactory(DynamoDBMapperConfig.DEFAULT.getTypeConverterFactory());
- }
-
- // Deprecated but the only way how DynamoDBMapperConfig#merge is exposed
- this.dynamoDBMapperConfig = new DynamoDBMapperConfig(dynamoDBMapperConfig, emptyBuilder.build());
- }
-
- if (dynamoDBMapper == null) {
- this.dynamoDBMapper = new DynamoDBMapper(amazonDynamoDB, dynamoDBMapperConfig);
- } else {
- this.dynamoDBMapper = dynamoDBMapper;
- }
+ this.amazonDynamoDB = amazonDynamoDB;
+ this.dynamoDBMapper = dynamoDBMapper;
+ this.dynamoDBMapperConfig = dynamoDBMapperConfig;
}
@Override
diff --git a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/cdi/DynamoDBRepositoryBean.java b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/cdi/DynamoDBRepositoryBean.java
index 2adc57fc..5104a68f 100644
--- a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/cdi/DynamoDBRepositoryBean.java
+++ b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/cdi/DynamoDBRepositoryBean.java
@@ -16,6 +16,7 @@
package org.socialsignin.spring.data.dynamodb.repository.cdi;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig;
import org.socialsignin.spring.data.dynamodb.core.DynamoDBOperations;
import org.socialsignin.spring.data.dynamodb.core.DynamoDBTemplate;
@@ -100,8 +101,13 @@ protected T create(CreationalContext creationalContext, Class repositoryTy
? null
: getDependencyInstance(dynamoDBOperationsBean, DynamoDBOperations.class);
+ if (dynamoDBMapperConfig == null) {
+ dynamoDBMapperConfig = DynamoDBMapperConfig.DEFAULT;
+ }
+ DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(amazonDynamoDB, dynamoDBMapperConfig);
+
if (dynamoDBOperations == null) {
- dynamoDBOperations = new DynamoDBTemplate(amazonDynamoDB, dynamoDBMapperConfig);
+ dynamoDBOperations = new DynamoDBTemplate(amazonDynamoDB, dynamoDBMapper, dynamoDBMapperConfig);
}
DynamoDBRepositoryFactory factory = new DynamoDBRepositoryFactory(dynamoDBOperations);
diff --git a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/config/DynamoDBMapperConfigFactory.java b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/config/DynamoDBMapperConfigFactory.java
new file mode 100644
index 00000000..36340e56
--- /dev/null
+++ b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/config/DynamoDBMapperConfigFactory.java
@@ -0,0 +1,83 @@
+/**
+ * Copyright © 2018 spring-data-dynamodb (https://github.com/derjust/spring-data-dynamodb)
+ *
+ * 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.socialsignin.spring.data.dynamodb.repository.config;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.lang.Nullable;
+
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig;
+
+public class DynamoDBMapperConfigFactory implements FactoryBean, BeanPostProcessor {
+ private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDBMapperConfigFactory.class);
+ @Override
+ public DynamoDBMapperConfig getObject() throws Exception {
+ return DynamoDBMapperConfig.DEFAULT;
+ }
+
+ @Override
+ public Class> getObjectType() {
+ return DynamoDBMapperConfig.class;
+ }
+
+ @Nullable
+ public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+ if (bean instanceof DynamoDBMapperConfig) {
+ DynamoDBMapperConfig dynamoDBMapperConfig = (DynamoDBMapperConfig) bean;
+ if (dynamoDBMapperConfig == DynamoDBMapperConfig.DEFAULT) {
+ return bean;
+ }
+ // #146, #81 #157
+ // Trying to fix half-initialized DynamoDBMapperConfigs here.
+ // The old documentation advised to start with an empty builder. Therefore we
+ // try here to set required fields to their defaults -
+ // As the documentation at
+ // https://github.com/derjust/spring-data-dynamodb/wiki/Alter-table-name-during-runtime
+ // (same as https://git.io/DynamoDBMapperConfig)
+ // now does: Start with #DEFAULT and add what's required
+ DynamoDBMapperConfig.Builder emptyBuilder = DynamoDBMapperConfig.builder(); // empty (!) builder
+
+ if (dynamoDBMapperConfig.getConversionSchema() == null) {
+ LOGGER.warn(
+ "No ConversionSchema set in the provided dynamoDBMapperConfig! Merging with DynamoDBMapperConfig.DEFAULT - Please see https://git.io/DynamoDBMapperConfig");
+ // DynamoDBMapperConfig#DEFAULT comes with a ConversionSchema
+ emptyBuilder.withConversionSchema(DynamoDBMapperConfig.DEFAULT.getConversionSchema());
+ }
+
+ if (dynamoDBMapperConfig.getTypeConverterFactory() == null) {
+ LOGGER.warn(
+ "No TypeConverterFactory set in the provided dynamoDBMapperConfig! Merging with DynamoDBMapperConfig.DEFAULT - Please see https://git.io/DynamoDBMapperConfig");
+ // DynamoDBMapperConfig#DEFAULT comes with a TypeConverterFactory
+ emptyBuilder.withTypeConverterFactory(DynamoDBMapperConfig.DEFAULT.getTypeConverterFactory());
+ }
+
+ return createDynamoDBMapperConfig(dynamoDBMapperConfig, emptyBuilder);
+
+ } else {
+ return bean;
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private DynamoDBMapperConfig createDynamoDBMapperConfig(DynamoDBMapperConfig dynamoDBMapperConfig,
+ DynamoDBMapperConfig.Builder emptyBuilder) {
+ // Deprecated but the only way how DynamoDBMapperConfig#merge is exposed
+ return new DynamoDBMapperConfig(dynamoDBMapperConfig, emptyBuilder.build());
+ }
+}
diff --git a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/config/DynamoDBMapperFactory.java b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/config/DynamoDBMapperFactory.java
new file mode 100644
index 00000000..20486acc
--- /dev/null
+++ b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/config/DynamoDBMapperFactory.java
@@ -0,0 +1,46 @@
+/**
+ * Copyright © 2018 spring-data-dynamodb (https://github.com/derjust/spring-data-dynamodb)
+ *
+ * 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.socialsignin.spring.data.dynamodb.repository.config;
+
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig;
+
+public class DynamoDBMapperFactory implements FactoryBean {
+
+ private final AmazonDynamoDB amazonDynamoDB;
+ private final DynamoDBMapperConfig dynamoDBMapperConfig;
+
+ @Autowired
+ public DynamoDBMapperFactory(AmazonDynamoDB amazonDynamoDB, DynamoDBMapperConfig dynamoDBMapperConfig) {
+ this.amazonDynamoDB = amazonDynamoDB;
+ this.dynamoDBMapperConfig = dynamoDBMapperConfig;
+ }
+
+ @Override
+ public DynamoDBMapper getObject() throws Exception {
+ return new DynamoDBMapper(amazonDynamoDB, dynamoDBMapperConfig);
+ }
+
+ @Override
+ public Class> getObjectType() {
+ return DynamoDBMapper.class;
+ }
+
+}
diff --git a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/config/DynamoDBRepositoryConfigExtension.java b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/config/DynamoDBRepositoryConfigExtension.java
index c691de90..af5fae4b 100644
--- a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/config/DynamoDBRepositoryConfigExtension.java
+++ b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/config/DynamoDBRepositoryConfigExtension.java
@@ -15,13 +15,23 @@
*/
package org.socialsignin.spring.data.dynamodb.repository.config;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.socialsignin.spring.data.dynamodb.core.DynamoDBTemplate;
import org.socialsignin.spring.data.dynamodb.mapping.DynamoDBMappingContext;
import org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBRepositoryFactoryBean;
+import org.socialsignin.spring.data.dynamodb.repository.util.DynamoDBMappingContextProcessor;
+import org.socialsignin.spring.data.dynamodb.repository.util.Entity2DynamoDBTableSynchronizer;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.data.config.ParsingUtils;
import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource;
import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport;
+import org.springframework.data.repository.config.RepositoryConfigurationSource;
import org.springframework.data.repository.config.XmlRepositoryConfigurationSource;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -33,6 +43,8 @@
*/
public class DynamoDBRepositoryConfigExtension extends RepositoryConfigurationExtensionSupport {
+ private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDBRepositoryConfigExtension.class);
+
private static final String DEFAULT_AMAZON_DYNAMO_DB_BEAN_NAME = "amazonDynamoDB";
private static final String DYNAMO_DB_MAPPER_CONFIG_REF = "dynamodb-mapper-config-ref";
@@ -43,6 +55,9 @@ public class DynamoDBRepositoryConfigExtension extends RepositoryConfigurationEx
private static final String MAPPING_CONTEXT_REF = "mapping-context-ref";
+ private BeanDefinitionRegistry registry;
+ private String defaultDynamoDBMappingContext;
+
@Override
public String getRepositoryFactoryBeanClassName() {
return DynamoDBRepositoryFactoryBean.class.getName();
@@ -52,9 +67,11 @@ public String getRepositoryFactoryBeanClassName() {
public void postProcess(BeanDefinitionBuilder builder, AnnotationRepositoryConfigurationSource config) {
AnnotationAttributes attributes = config.getAttributes();
- postProcess(builder, attributes.getString("amazonDynamoDBRef"), attributes.getString("dynamoDBMapperConfigRef"),
- attributes.getString("dynamoDBOperationsRef"), attributes.getString("mappingContextRef"));
+ String repositoryBeanName = config.generateBeanName(builder.getBeanDefinition());
+ postProcess(builder, repositoryBeanName, attributes.getString("amazonDynamoDBRef"),
+ attributes.getString("dynamoDBMapperConfigRef"), attributes.getString("dynamoDBOperationsRef"),
+ attributes.getString("mappingContextRef"));
}
/*
@@ -68,18 +85,28 @@ public void postProcess(BeanDefinitionBuilder builder, AnnotationRepositoryConfi
*/
@Override
public void postProcess(BeanDefinitionBuilder builder, XmlRepositoryConfigurationSource config) {
-
Element element = config.getElement();
ParsingUtils.setPropertyReference(builder, element, AMAZON_DYNAMODB_REF, "amazonDynamoDB");
ParsingUtils.setPropertyReference(builder, element, DYNAMO_DB_MAPPER_CONFIG_REF, "dynamoDBMapperConfig");
ParsingUtils.setPropertyReference(builder, element, DYNAMO_DB_OPERATIONS_REF, "dynamoDBOperations");
- ParsingUtils.setPropertyReference(builder, element, MAPPING_CONTEXT_REF, "dynamoDBMappingContext");
+ String dynamoDBMappingContextRef = element.getAttribute(MAPPING_CONTEXT_REF);
+
+ if (!StringUtils.hasText(dynamoDBMappingContextRef)) {
+ // Register DynamoDBMappingContext only once if necessary
+ if (defaultDynamoDBMappingContext == null) {
+ defaultDynamoDBMappingContext = registerDynamoDBMappingContext(registry);
+ }
+ dynamoDBMappingContextRef = defaultDynamoDBMappingContext;
+
+ }
+ registerAndSetPostProcessingBeans(builder, registry, dynamoDBMappingContextRef);
}
- private void postProcess(BeanDefinitionBuilder builder, String amazonDynamoDBRef, String dynamoDBMapperConfigRef,
- String dynamoDBOperationsRef, String dynamoDBMappingContextRef) {
+ private Map dynamoDBTemplateCache = new HashMap<>();
+ private void postProcess(BeanDefinitionBuilder builder, String repositoryName, String amazonDynamoDBRef,
+ String dynamoDBMapperConfigRef, String dynamoDBOperationsRef, String dynamoDBMappingContextRef) {
if (StringUtils.hasText(dynamoDBOperationsRef)) {
builder.addPropertyReference("dynamoDBOperations", dynamoDBOperationsRef);
@@ -89,22 +116,129 @@ private void postProcess(BeanDefinitionBuilder builder, String amazonDynamoDBRef
"Cannot specify both dynamoDBMapperConfigBean bean and dynamoDBOperationsBean in repository configuration");
} else {
- amazonDynamoDBRef = StringUtils.hasText(amazonDynamoDBRef)
- ? amazonDynamoDBRef
- : DEFAULT_AMAZON_DYNAMO_DB_BEAN_NAME;
+ if (StringUtils.isEmpty(dynamoDBOperationsRef)) {
+
+ String dynamoDBRef;
+ if (StringUtils.hasText(amazonDynamoDBRef)) {
+ dynamoDBRef = amazonDynamoDBRef;
+ } else {
+ dynamoDBRef = DEFAULT_AMAZON_DYNAMO_DB_BEAN_NAME;
+ }
- builder.addPropertyReference("amazonDynamoDB", amazonDynamoDBRef);
+ dynamoDBOperationsRef = dynamoDBTemplateCache
+ .computeIfAbsent(getBeanNameWithModulePrefix("DynamoDBTemplate-" + dynamoDBRef), ref -> {
+ BeanDefinitionBuilder dynamoDBTemplateBuilder = BeanDefinitionBuilder
+ .genericBeanDefinition(DynamoDBTemplate.class);
+ dynamoDBTemplateBuilder.addConstructorArgReference(dynamoDBRef);
+
+ registry.registerBeanDefinition(ref, dynamoDBTemplateBuilder.getBeanDefinition());
+ return ref;
+ });
+ }
+
+ builder.addPropertyReference("dynamoDBOperations", dynamoDBOperationsRef);
if (StringUtils.hasText(dynamoDBMapperConfigRef)) {
builder.addPropertyReference("dynamoDBMapperConfig", dynamoDBMapperConfigRef);
}
}
- if (StringUtils.hasText(dynamoDBMappingContextRef)) {
- builder.addPropertyReference("dynamoDBMappingContext", dynamoDBMappingContextRef);
- } else {
- builder.addPropertyValue("dynamoDBMappingContext", new DynamoDBMappingContext());
+ if (!StringUtils.hasText(dynamoDBMappingContextRef)) {
+ // Register DynamoDBMappingContext only once if necessary
+ if (defaultDynamoDBMappingContext == null) {
+ defaultDynamoDBMappingContext = registerDynamoDBMappingContext(registry);
+ }
+ dynamoDBMappingContextRef = defaultDynamoDBMappingContext;
+
}
+
+ builder.addPropertyReference("dynamoDBMappingContext", dynamoDBMappingContextRef);
+ registerAndSetPostProcessingBeans(builder, registry, dynamoDBMappingContextRef);
+ }
+
+ protected void registerAndSetPostProcessingBeans(BeanDefinitionBuilder builder, BeanDefinitionRegistry registry,
+ String dynamoDBMappingContextRef) {
+ String tableSynchronizerName = registerEntity2DynamoDBTableSynchronizer(registry, dynamoDBMappingContextRef);
+ builder.addPropertyReference("entity2DynamoDBTableSynchronizer", tableSynchronizerName);
+
+ String dynamoDBMappingContextProcessorName = registerDynamoDBMappingContextProcessor(registry,
+ dynamoDBMappingContextRef);
+ builder.addPropertyReference("dynamoDBMappingContextProcessor", dynamoDBMappingContextProcessorName);
+ }
+
+ private final Map entity2DynamoDBTableSynchronizerCache = new ConcurrentHashMap<>();
+ private String registerEntity2DynamoDBTableSynchronizer(BeanDefinitionRegistry registry,
+ String dynamoDBMappingContextRef) {
+ assert registry != null;
+
+ return entity2DynamoDBTableSynchronizerCache.computeIfAbsent(dynamoDBMappingContextRef, ref -> {
+ BeanDefinitionBuilder entity2DynamoDBTableSynchronizerBuilder = BeanDefinitionBuilder
+ .genericBeanDefinition(Entity2DynamoDBTableSynchronizer.class);
+ String tableSynchronizerName = getBeanNameWithModulePrefix(
+ "Entity2DynamoDBTableSynchronizer-" + dynamoDBMappingContextRef);
+ registry.registerBeanDefinition(tableSynchronizerName,
+ entity2DynamoDBTableSynchronizerBuilder.getBeanDefinition());
+
+ return tableSynchronizerName;
+ });
+ }
+
+ private final Map dynamoDBMappingContextProcessorCache = new ConcurrentHashMap<>();
+ private String registerDynamoDBMappingContextProcessor(BeanDefinitionRegistry registry,
+ String dynamoDBMappingContextRef) {
+ assert registry != null;
+
+ return dynamoDBMappingContextProcessorCache.computeIfAbsent(dynamoDBMappingContextRef, ref -> {
+ BeanDefinitionBuilder dynamoDBMappingContextProcessorBuilder = BeanDefinitionBuilder
+ .genericBeanDefinition(DynamoDBMappingContextProcessor.class);
+ dynamoDBMappingContextProcessorBuilder.addConstructorArgReference(dynamoDBMappingContextRef);
+
+ String dynamoDBMappingContextProcessorRef = getBeanNameWithModulePrefix(
+ "DynamoDBMappingContextProcessor-" + dynamoDBMappingContextRef);
+ registry.registerBeanDefinition(dynamoDBMappingContextProcessorRef,
+ dynamoDBMappingContextProcessorBuilder.getBeanDefinition());
+
+ return dynamoDBMappingContextProcessorRef;
+
+ });
+ }
+
+ private String registerDynamoDBMappingContext(BeanDefinitionRegistry registry) {
+ assert registry != null;
+
+ BeanDefinitionBuilder dynamoDBMappingContextBuilder = BeanDefinitionBuilder
+ .genericBeanDefinition(DynamoDBMappingContext.class);
+ String dynamoDBMappingContextRef = getBeanNameWithModulePrefix("DynamoDBMappingContext");
+
+ LOGGER.debug("Adding bean <{}> of type <{}>", dynamoDBMappingContextRef,
+ dynamoDBMappingContextBuilder.getBeanDefinition());
+
+ registry.registerBeanDefinition(dynamoDBMappingContextRef, dynamoDBMappingContextBuilder.getBeanDefinition());
+
+ return dynamoDBMappingContextRef;
+ }
+
+ @Override
+ public void registerBeansForRoot(BeanDefinitionRegistry registry,
+ RepositoryConfigurationSource configurationSource) {
+ super.registerBeansForRoot(registry, configurationSource);
+
+ // Store for later to be used by #postProcess, too
+ this.registry = registry;
+
+ BeanDefinitionBuilder dynamoDBMapperConfigBuiilder = BeanDefinitionBuilder
+ .genericBeanDefinition(DynamoDBMapperConfigFactory.class);
+ registry.registerBeanDefinition(getBeanNameWithModulePrefix("DynamoDBMapperConfig"),
+ dynamoDBMapperConfigBuiilder.getBeanDefinition());
+
+ BeanDefinitionBuilder dynamoDBMapperBuilder = BeanDefinitionBuilder
+ .genericBeanDefinition(DynamoDBMapperFactory.class);
+ registry.registerBeanDefinition(getBeanNameWithModulePrefix("DynamoDBMapper"),
+ dynamoDBMapperBuilder.getBeanDefinition());
+ }
+
+ protected String getBeanNameWithModulePrefix(String baseBeanName) {
+ return String.format("%s-%s", getModulePrefix(), baseBeanName);
}
@Override
diff --git a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/config/EnableDynamoDBRepositories.java b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/config/EnableDynamoDBRepositories.java
index bb2f9190..a5e68afc 100644
--- a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/config/EnableDynamoDBRepositories.java
+++ b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/config/EnableDynamoDBRepositories.java
@@ -15,11 +15,6 @@
*/
package org.socialsignin.spring.data.dynamodb.repository.config;
-import org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBRepositoryFactoryBean;
-import org.springframework.context.annotation.ComponentScan.Filter;
-import org.springframework.context.annotation.Import;
-import org.springframework.data.repository.query.QueryLookupStrategy.Key;
-
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
@@ -27,6 +22,11 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBRepositoryFactoryBean;
+import org.springframework.context.annotation.ComponentScan.Filter;
+import org.springframework.context.annotation.Import;
+import org.springframework.data.repository.query.QueryLookupStrategy.Key;
+
/**
* Annotation to enable DynamoDB repositories. Will scan the package of the
* annotated configuration class for Spring Data repositories by default.
diff --git a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/query/AbstractDynamoDBQueryCriteria.java b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/query/AbstractDynamoDBQueryCriteria.java
index 21667d95..5ea4087c 100644
--- a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/query/AbstractDynamoDBQueryCriteria.java
+++ b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/query/AbstractDynamoDBQueryCriteria.java
@@ -180,8 +180,8 @@ protected void applySortIfSpecified(QueryRequest queryRequest, List perm
queryRequest.setScanIndexForward(order.getDirection().equals(Direction.ASC));
sortAlreadySet = true;
} else {
- throw new UnsupportedOperationException(
- "Sorting only possible by " + permittedPropertyNames + " for the criteria specified");
+ throw new UnsupportedOperationException("Sorting only possible by " + permittedPropertyNames
+ + " for the criteria specified and not for " + order.getProperty());
}
}
}
diff --git a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/support/DynamoDBRepositoryFactory.java b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/support/DynamoDBRepositoryFactory.java
index 8e589597..81b6e0c2 100644
--- a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/support/DynamoDBRepositoryFactory.java
+++ b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/support/DynamoDBRepositoryFactory.java
@@ -30,7 +30,6 @@
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
import org.springframework.data.util.Version;
-import java.io.Serializable;
import java.util.Optional;
import java.util.StringTokenizer;
@@ -96,13 +95,12 @@ protected static boolean isCompatible(String spec, String impl) {
public DynamoDBRepositoryFactory(DynamoDBOperations dynamoDBOperations) {
this.dynamoDBOperations = dynamoDBOperations;
-
}
@Override
public DynamoDBEntityInformation getEntityInformation(final Class domainClass) {
- final DynamoDBEntityMetadataSupport metadata = new DynamoDBEntityMetadataSupport(domainClass);
+ final DynamoDBEntityMetadataSupport metadata = new DynamoDBEntityMetadataSupport<>(domainClass);
return metadata.getEntityInformation();
}
@@ -126,8 +124,7 @@ protected Optional getQueryLookupStrategy(Key key,
* @return the created {@link DynamoDBCrudRepository} instance
*/
@SuppressWarnings({"unchecked", "rawtypes"})
- protected DynamoDBCrudRepository, ?> getDynamoDBRepository(
- RepositoryMetadata metadata) {
+ protected DynamoDBCrudRepository, ?> getDynamoDBRepository(RepositoryMetadata metadata) {
return new SimpleDynamoDBPagingAndSortingRepository(getEntityInformation(metadata.getDomainType()),
dynamoDBOperations, getEnableScanPermissions(metadata));
}
diff --git a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/support/DynamoDBRepositoryFactoryBean.java b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/support/DynamoDBRepositoryFactoryBean.java
index c9dcc290..66f46624 100644
--- a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/support/DynamoDBRepositoryFactoryBean.java
+++ b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/support/DynamoDBRepositoryFactoryBean.java
@@ -15,14 +15,11 @@
*/
package org.socialsignin.spring.data.dynamodb.repository.support;
-import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
-import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig;
import org.socialsignin.spring.data.dynamodb.core.DynamoDBOperations;
-import org.socialsignin.spring.data.dynamodb.core.DynamoDBTemplate;
import org.socialsignin.spring.data.dynamodb.mapping.DynamoDBMappingContext;
-import org.springframework.beans.BeansException;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
+import org.socialsignin.spring.data.dynamodb.repository.util.DynamoDBMappingContextProcessor;
+import org.socialsignin.spring.data.dynamodb.repository.util.Entity2DynamoDBTableSynchronizer;
+import org.springframework.beans.factory.annotation.Required;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
@@ -41,53 +38,44 @@
*/
public class DynamoDBRepositoryFactoryBean, S, ID extends Serializable>
extends
- RepositoryFactoryBeanSupport
- implements
- ApplicationContextAware {
-
- private DynamoDBMapperConfig dynamoDBMapperConfig;
-
- private AmazonDynamoDB amazonDynamoDB;
+ RepositoryFactoryBeanSupport {
private DynamoDBOperations dynamoDBOperations;
-
- private ApplicationContext applicationContext;
+ private Entity2DynamoDBTableSynchronizer tableSynchronizer;
+ private DynamoDBMappingContextProcessor dynamoDBMappingContextProcessor;
public DynamoDBRepositoryFactoryBean(Class extends T> repositoryInterface) {
super(repositoryInterface);
}
- public void setAmazonDynamoDB(AmazonDynamoDB amazonDynamoDB) {
- this.amazonDynamoDB = amazonDynamoDB;
- }
-
@Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- this.applicationContext = applicationContext;
+ protected RepositoryFactorySupport createRepositoryFactory() {
+ assert dynamoDBOperations != null;
+ assert tableSynchronizer != null;
+ assert dynamoDBMappingContextProcessor != null;
+ DynamoDBRepositoryFactory dynamoDBRepositoryFactory = new DynamoDBRepositoryFactory(dynamoDBOperations);
+ dynamoDBRepositoryFactory.addRepositoryProxyPostProcessor(tableSynchronizer);
+ dynamoDBRepositoryFactory.addRepositoryProxyPostProcessor(dynamoDBMappingContextProcessor);
+ return dynamoDBRepositoryFactory;
}
- @Override
- protected RepositoryFactorySupport createRepositoryFactory() {
- if (dynamoDBOperations == null) {
- /**
- * The ApplicationContextAware within DynamoDBTemplate is not executed as
- * DynamoDBTemplate is not initialized as a bean
- */
- DynamoDBTemplate dynamoDBTemplate = new DynamoDBTemplate(amazonDynamoDB, dynamoDBMapperConfig);
- dynamoDBTemplate.setApplicationContext(applicationContext);
- dynamoDBOperations = dynamoDBTemplate;
- }
- return new DynamoDBRepositoryFactory(dynamoDBOperations);
+ @Required
+ public void setDynamoDBMappingContextProcessor(
+ DynamoDBMappingContextProcessor dynamoDBMappingContextProcessor) {
+ this.dynamoDBMappingContextProcessor = dynamoDBMappingContextProcessor;
}
- public void setDynamoDBMapperConfig(DynamoDBMapperConfig dynamoDBMapperConfig) {
- this.dynamoDBMapperConfig = dynamoDBMapperConfig;
+ @Required
+ public void setEntity2DynamoDBTableSynchronizer(Entity2DynamoDBTableSynchronizer tableSynchronizer) {
+ this.tableSynchronizer = tableSynchronizer;
}
+ @Required
public void setDynamoDBOperations(DynamoDBOperations dynamoDBOperations) {
this.dynamoDBOperations = dynamoDBOperations;
}
+ @Required
public void setDynamoDBMappingContext(DynamoDBMappingContext dynamoDBMappingContext) {
setMappingContext(dynamoDBMappingContext);
}
diff --git a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/support/SimpleDynamoDBCrudRepository.java b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/support/SimpleDynamoDBCrudRepository.java
index be337ab4..05dfa0cd 100644
--- a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/support/SimpleDynamoDBCrudRepository.java
+++ b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/support/SimpleDynamoDBCrudRepository.java
@@ -24,6 +24,7 @@
import org.socialsignin.spring.data.dynamodb.utils.ExceptionHandler;
import org.socialsignin.spring.data.dynamodb.utils.SortHandler;
import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
import java.util.Collections;
@@ -93,7 +94,7 @@ public List findAllById(Iterable ids) {
AtomicInteger idx = new AtomicInteger();
List keyPairs = StreamSupport.stream(ids.spliterator(), false).map(id -> {
- Assert.notNull(id, "The given id at position " + idx.getAndIncrement() + " must not be null!");
+ Assert.notNull(id, "The given id at position " + idx.getAndIncrement() + " must not be null!");
if (entityInformation.isRangeKeyAware()) {
return new KeyPair().withHashKey(entityInformation.getHashKey(id))
@@ -202,4 +203,8 @@ public void deleteAll() {
dynamoDBOperations.batchDelete(findAll());
}
+ @NonNull
+ public DynamoDBEntityInformation getEntityInformation() {
+ return this.entityInformation;
+ }
}
diff --git a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/util/DynamoDBMappingContextProcessor.java b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/util/DynamoDBMappingContextProcessor.java
new file mode 100644
index 00000000..8800cc03
--- /dev/null
+++ b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/util/DynamoDBMappingContextProcessor.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright © 2018 spring-data-dynamodb (https://github.com/derjust/spring-data-dynamodb)
+ *
+ * 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.socialsignin.spring.data.dynamodb.repository.util;
+
+import org.socialsignin.spring.data.dynamodb.mapping.DynamoDBMappingContext;
+import org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBEntityInformation;
+import org.springframework.data.repository.core.support.RepositoryProxyPostProcessor;
+
+public class DynamoDBMappingContextProcessor extends EntityInformationProxyPostProcessor
+ implements
+ RepositoryProxyPostProcessor {
+
+ private final DynamoDBMappingContext context;
+
+ public DynamoDBMappingContextProcessor(DynamoDBMappingContext context) {
+ this.context = context;
+ }
+
+ @Override
+ protected void registeredEntity(DynamoDBEntityInformation entityInformation) {
+ // register entities
+ context.getPersistentEntity(entityInformation.getJavaType());
+ }
+
+}
diff --git a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/util/Entity2DDL.java b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/util/Entity2DDL.java
new file mode 100644
index 00000000..9795aa3c
--- /dev/null
+++ b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/util/Entity2DDL.java
@@ -0,0 +1,80 @@
+/**
+ * Copyright © 2018 spring-data-dynamodb (https://github.com/derjust/spring-data-dynamodb)
+ *
+ * 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.socialsignin.spring.data.dynamodb.repository.util;
+
+/**
+ * Configuration key is {@code spring.data.dynamodb.entity2ddl.auto} Inspired by
+ * Hibernate's hbm2ddl
+ *
+ * @see Hibernate
+ * User Guide
+ */
+public enum Entity2DDL {
+ /** No action will be performed. */
+ NONE("none"),
+
+ /** Database creation will be generated on ApplicationContext startup. */
+ CREATE_ONLY("create-only"),
+
+ /** Database dropping will be generated on ApplicationContext shutdown. */
+ DROP("drop"),
+
+ /**
+ * Database dropping will be generated followed by database creation on
+ * ApplicationContext startup.
+ */
+ CREATE("create"),
+
+ /**
+ * Drop the schema and recreate it on ApplicationContext startup. Additionally,
+ * drop the schema on ApplicationContext shutdown.
+ */
+ CREATE_DROP("create-drop"),
+
+ /** Validate the database schema */
+ VALIDATE("validate");
+
+ private final String configurationValue;
+
+ Entity2DDL(String configurationValue) {
+ this.configurationValue = configurationValue;
+ }
+
+ public String getConfigurationValue() {
+ return this.configurationValue;
+ }
+
+ /**
+ * Use this in place of valueOf.
+ *
+ * @param value
+ * real value
+ * @return Entity2DDL corresponding to the value
+ *
+ * @throws IllegalArgumentException
+ * If the specified value does not map to one of the known values in
+ * this enum.
+ */
+ public static Entity2DDL fromValue(String value) {
+ for (Entity2DDL resolvedConfig : Entity2DDL.values()) {
+ if (resolvedConfig.configurationValue.equals(value)) {
+ return resolvedConfig;
+ }
+ }
+ throw new IllegalArgumentException(value + " is not a valid configuration value!");
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/util/Entity2DynamoDBTableSynchronizer.java b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/util/Entity2DynamoDBTableSynchronizer.java
new file mode 100644
index 00000000..51595528
--- /dev/null
+++ b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/util/Entity2DynamoDBTableSynchronizer.java
@@ -0,0 +1,229 @@
+/**
+ * Copyright © 2018 spring-data-dynamodb (https://github.com/derjust/spring-data-dynamodb)
+ *
+ * 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.socialsignin.spring.data.dynamodb.repository.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.stream.Collectors;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBEntityInformation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ApplicationContextEvent;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.context.event.ContextStoppedEvent;
+import org.springframework.data.repository.core.support.RepositoryProxyPostProcessor;
+
+import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
+import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
+import com.amazonaws.services.dynamodbv2.model.DeleteTableRequest;
+import com.amazonaws.services.dynamodbv2.model.DescribeTableResult;
+import com.amazonaws.services.dynamodbv2.model.Projection;
+import com.amazonaws.services.dynamodbv2.model.ProjectionType;
+import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
+import com.amazonaws.services.dynamodbv2.model.TableDescription;
+import com.amazonaws.services.dynamodbv2.util.TableUtils;
+import com.amazonaws.services.dynamodbv2.util.TableUtils.TableNeverTransitionedToStateException;
+
+/**
+ * This is the base class for all classes performing the validation or
+ * auto-creation of tables based on the entity classes.
+ *
+ * //TODO: It would be nice if the checks would run in parallel via a
+ * TaskScheduler (if available)
+ *
+ * @see Entity2DDL
+ */
+public class Entity2DynamoDBTableSynchronizer extends EntityInformationProxyPostProcessor
+ implements
+ RepositoryProxyPostProcessor,
+ ApplicationListener {
+ private static final Logger LOGGER = LoggerFactory.getLogger(Entity2DynamoDBTableSynchronizer.class);
+
+ private static final String CONFIGURATION_KEY_entity2ddl_auto = "${spring.data.dynamodb.entity2ddl.auto:none}";
+ private static final String CONFIGURATION_KEY_entity2ddl_gsiProjectionType = "${spring.data.dynamodb.entity2ddl.gsiProjectionType:ALL}";
+ private static final String CONFIGURATION_KEY_entity2ddl_readCapacity = "${spring.data.dynamodb.entity2ddl.readCapacity:10}";
+ private static final String CONFIGURATION_KEY_entity2ddl_writeCapacity = "${spring.data.dynamodb.entity2ddl.writeCapacity:1}";
+
+ private final AmazonDynamoDB amazonDynamoDB;
+ private final DynamoDBMapper mapper;
+
+ private final Entity2DDL mode;
+ private final ProjectionType gsiProjectionType;
+ private final ProvisionedThroughput pt;
+
+ private final Collection> registeredEntities = new ArrayList<>();
+
+ public Entity2DynamoDBTableSynchronizer(AmazonDynamoDB amazonDynamoDB, DynamoDBMapper mapper, Entity2DDL mode) {
+ this(amazonDynamoDB, mapper, mode.getConfigurationValue(), ProjectionType.ALL.name(), 10L, 10L);
+ }
+
+ @Autowired
+ public Entity2DynamoDBTableSynchronizer(AmazonDynamoDB amazonDynamoDB, DynamoDBMapper mapper,
+ @Value(CONFIGURATION_KEY_entity2ddl_auto) String mode,
+ @Value(CONFIGURATION_KEY_entity2ddl_gsiProjectionType) String gsiProjectionType,
+ @Value(CONFIGURATION_KEY_entity2ddl_readCapacity) long readCapacity,
+ @Value(CONFIGURATION_KEY_entity2ddl_writeCapacity) long writeCapacity) {
+ this.amazonDynamoDB = amazonDynamoDB;
+ this.mapper = mapper;
+
+ this.mode = Entity2DDL.fromValue(mode);
+ this.pt = new ProvisionedThroughput(readCapacity, writeCapacity);
+ this.gsiProjectionType = ProjectionType.fromValue(gsiProjectionType);
+ }
+
+ @Override
+ protected void registeredEntity(DynamoDBEntityInformation entityInformation) {
+ this.registeredEntities.add(entityInformation);
+ }
+
+ @Override
+ public void onApplicationEvent(ApplicationContextEvent event) {
+ LOGGER.info("Checking repository classes with DynamoDB tables {} for {}",
+ registeredEntities.stream().map(e -> e.getDynamoDBTableName()).collect(Collectors.joining(", ")),
+ event.getClass().getSimpleName());
+
+ for (DynamoDBEntityInformation entityInformation : registeredEntities) {
+
+ try {
+ synchronize(entityInformation, event);
+ } catch (TableNeverTransitionedToStateException | InterruptedException e) {
+ throw new RuntimeException("Could not perform Entity2DDL operation " + mode + " on "
+ + entityInformation.getDynamoDBTableName(), e);
+ }
+ }
+ }
+
+ protected void synchronize(DynamoDBEntityInformation entityInformation, ApplicationContextEvent event)
+ throws TableNeverTransitionedToStateException, InterruptedException {
+
+ if (event instanceof ContextRefreshedEvent) {
+ switch (mode) {
+ case CREATE_DROP :
+ case CREATE :
+ performDrop(entityInformation);
+ // TODO implement wait for deletion
+ case CREATE_ONLY :
+ performCreate(entityInformation);
+ break;
+ case VALIDATE :
+ performValidate(entityInformation);
+ break;
+ case DROP :
+ case NONE :
+ default :
+ LOGGER.debug("No auto table DDL performed on start");
+ break;
+ }
+ } else if (event instanceof ContextStoppedEvent) {
+ switch (mode) {
+ case CREATE_DROP :
+ case DROP :
+ performDrop(entityInformation);
+ performCreate(entityInformation);
+ break;
+
+ case CREATE :
+ case VALIDATE :
+ case NONE :
+ default :
+ LOGGER.debug("No auto table DDL performed on stop");
+ break;
+ }
+ } else {
+ LOGGER.trace("Ignored ApplicationContextEvent: {}", event);
+ }
+
+ }
+
+ private boolean performCreate(DynamoDBEntityInformation entityInformation)
+ throws TableNeverTransitionedToStateException, InterruptedException {
+ Class domainType = entityInformation.getJavaType();
+
+ CreateTableRequest ctr = mapper.generateCreateTableRequest(domainType);
+ LOGGER.trace("Creating table {} for entity {}", ctr.getTableName(), domainType);
+ ctr.setProvisionedThroughput(pt);
+
+ if (ctr.getGlobalSecondaryIndexes() != null) {
+ ctr.getGlobalSecondaryIndexes().forEach(gsi -> {
+ gsi.setProjection(new Projection().withProjectionType(gsiProjectionType));
+ gsi.setProvisionedThroughput(pt);
+ });
+ }
+
+ boolean result = TableUtils.createTableIfNotExists(amazonDynamoDB, ctr);
+ if (result) {
+ TableUtils.waitUntilActive(amazonDynamoDB, ctr.getTableName());
+ LOGGER.debug("Created table {} for entity {}", ctr.getTableName(), domainType);
+ }
+ return result;
+ }
+
+ private boolean performDrop(DynamoDBEntityInformation entityInformation) {
+ Class domainType = entityInformation.getJavaType();
+
+ DeleteTableRequest dtr = mapper.generateDeleteTableRequest(domainType);
+ LOGGER.trace("Dropping table {} for entity {}", dtr.getTableName(), domainType);
+
+ boolean result = TableUtils.deleteTableIfExists(amazonDynamoDB, dtr);
+ if (result) {
+ LOGGER.debug("Deleted table {} for entity {}", dtr.getTableName(), domainType);
+ }
+
+ return result;
+ }
+
+ /**
+ * @param entityInformation
+ * The entity to check for it's table
+ * @throws IllegalStateException
+ * is thrown if the existing table doesn't match the entity's
+ * annotation
+ */
+ private DescribeTableResult performValidate(DynamoDBEntityInformation entityInformation)
+ throws IllegalStateException {
+ Class domainType = entityInformation.getJavaType();
+
+ CreateTableRequest expected = mapper.generateCreateTableRequest(domainType);
+ DescribeTableResult result = amazonDynamoDB.describeTable(expected.getTableName());
+ TableDescription actual = result.getTable();
+
+ if (!expected.getKeySchema().equals(actual.getKeySchema())) {
+ throw new IllegalStateException("KeySchema is not as expected. Expected: <" + expected.getKeySchema()
+ + "> but found <" + actual.getKeySchema() + ">");
+ }
+ LOGGER.debug("KeySchema is valid");
+
+ if (expected.getGlobalSecondaryIndexes() != null) {
+ if (!Arrays.deepEquals(expected.getGlobalSecondaryIndexes().toArray(),
+ actual.getGlobalSecondaryIndexes().toArray())) {
+ throw new IllegalStateException("Global Secondary Indexes are not as expected. Expected: <"
+ + expected.getGlobalSecondaryIndexes() + "> but found <" + actual.getGlobalSecondaryIndexes()
+ + ">");
+ }
+ }
+ LOGGER.debug("Global Secondary Indexes are valid");
+
+ LOGGER.info("Validated table {} for entity{}", expected.getTableName(), domainType);
+ return result;
+ }
+
+}
diff --git a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/util/EntityInformationProxyPostProcessor.java b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/util/EntityInformationProxyPostProcessor.java
new file mode 100644
index 00000000..19f75dba
--- /dev/null
+++ b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/util/EntityInformationProxyPostProcessor.java
@@ -0,0 +1,49 @@
+/**
+ * Copyright © 2018 spring-data-dynamodb (https://github.com/derjust/spring-data-dynamodb)
+ *
+ * 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.socialsignin.spring.data.dynamodb.repository.util;
+
+import org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBEntityInformation;
+import org.socialsignin.spring.data.dynamodb.repository.support.SimpleDynamoDBCrudRepository;
+import org.springframework.aop.TargetSource;
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.data.repository.core.RepositoryInformation;
+import org.springframework.data.repository.core.support.RepositoryProxyPostProcessor;
+
+public abstract class EntityInformationProxyPostProcessor implements RepositoryProxyPostProcessor {
+
+ protected abstract void registeredEntity(DynamoDBEntityInformation entityInformation);
+
+ @Override
+ public final void postProcess(ProxyFactory factory, RepositoryInformation repositoryInformation) {
+ try {
+ TargetSource targetSource = factory.getTargetSource();
+ // assert
+ // targetSource.getTargetClass().equals(SimpleDynamoDBCrudRepository.class);
+
+ @SuppressWarnings("unchecked")
+ SimpleDynamoDBCrudRepository target = SimpleDynamoDBCrudRepository.class
+ .cast(targetSource.getTarget());
+
+ assert target != null;
+ DynamoDBEntityInformation entityInformation = target.getEntityInformation();
+ registeredEntity(entityInformation);
+
+ } catch (Exception e) {
+ throw new RuntimeException("Could not extract SimpleDynamoDBCrudRepository from " + factory, e);
+ }
+ }
+
+}
diff --git a/src/spotbugs-exclude.xml b/src/spotbugs-exclude.xml
new file mode 100644
index 00000000..a014e81e
--- /dev/null
+++ b/src/spotbugs-exclude.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/config/AuditingViaJavaConfigRepositoriesIT.java b/src/test/java/org/socialsignin/spring/data/dynamodb/config/AuditingViaJavaConfigRepositoriesIT.java
index fab032b0..b1ead7fb 100644
--- a/src/test/java/org/socialsignin/spring/data/dynamodb/config/AuditingViaJavaConfigRepositoriesIT.java
+++ b/src/test/java/org/socialsignin/spring/data/dynamodb/config/AuditingViaJavaConfigRepositoriesIT.java
@@ -15,34 +15,22 @@
*/
package org.socialsignin.spring.data.dynamodb.config;
-import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
-
-import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
-import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
-import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-import org.mockito.quality.Strictness;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.socialsignin.spring.data.dynamodb.domain.sample.AuditableUser;
import org.socialsignin.spring.data.dynamodb.domain.sample.AuditableUserRepository;
-import org.socialsignin.spring.data.dynamodb.mapping.DynamoDBMappingContext;
import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories;
import org.socialsignin.spring.data.dynamodb.utils.DynamoDBLocalResource;
-import org.socialsignin.spring.data.dynamodb.utils.TableCreationListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.AuditorAware;
import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.TestExecutionListeners;
+import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.Optional;
@@ -52,7 +40,6 @@
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doReturn;
-import static org.springframework.test.context.TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS;
/**
* Integration tests for auditing via Java config.
@@ -61,12 +48,8 @@
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {DynamoDBLocalResource.class, AuditingViaJavaConfigRepositoriesIT.TestAppConfig.class})
-@TestExecutionListeners(listeners = TableCreationListener.class, mergeMode = MERGE_WITH_DEFAULTS)
+@TestPropertySource(properties = {"spring.data.dynamodb.entity2ddl.auto=create"})
public class AuditingViaJavaConfigRepositoriesIT {
- @Rule
- public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.LENIENT);
- @Mock
- private static AuditorAware auditorProviderClass;
private static final Logger LOGGER = LoggerFactory.getLogger(AuditingViaJavaConfigRepositoriesIT.class);
@@ -78,18 +61,9 @@ public static class TestAppConfig {
@SuppressWarnings("unchecked")
@Bean(name = "auditorProvider")
public AuditorAware auditorProvider() {
- LOGGER.info("auditorProvider");
+ LOGGER.info("mocked auditorProvider provided");
return Mockito.mock(AuditorAware.class);
}
-
- @Bean
- public DynamoDBMappingContext dynamoDBMappingContext() {
- DynamoDBMappingContext mappingContext = new DynamoDBMappingContext();
- // Register entity
- // TODO but this shouldn't be nessassary?!
- mappingContext.getPersistentEntity(AuditableUser.class);
- return mappingContext;
- }
}
@Autowired
@@ -100,16 +74,8 @@ public DynamoDBMappingContext dynamoDBMappingContext() {
AuditableUser auditor;
- @Autowired
- private AmazonDynamoDB ddb;
-
@Before
public void setUp() throws InterruptedException {
- CreateTableRequest ctr = new DynamoDBMapper(ddb).generateCreateTableRequest(AuditableUser.class);
- ctr.withProvisionedThroughput(new ProvisionedThroughput(10L, 10L));
- ddb.createTable(ctr);
- // Thread.sleep(5 * 1000);
-
this.auditor = auditableUserRepository.save(new AuditableUser("auditor"));
assertThat(this.auditor, is(notNullValue()));
diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/core/CustomerHistoryIT.java b/src/test/java/org/socialsignin/spring/data/dynamodb/core/CustomerHistoryTest.java
similarity index 79%
rename from src/test/java/org/socialsignin/spring/data/dynamodb/core/CustomerHistoryIT.java
rename to src/test/java/org/socialsignin/spring/data/dynamodb/core/CustomerHistoryTest.java
index 86ae7f93..1147682a 100644
--- a/src/test/java/org/socialsignin/spring/data/dynamodb/core/CustomerHistoryIT.java
+++ b/src/test/java/org/socialsignin/spring/data/dynamodb/core/CustomerHistoryTest.java
@@ -20,20 +20,22 @@
import org.socialsignin.spring.data.dynamodb.domain.sample.CustomerHistory;
import org.socialsignin.spring.data.dynamodb.domain.sample.CustomerHistoryRepository;
import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories;
-import org.socialsignin.spring.data.dynamodb.utils.DynamoDBResource;
+import org.socialsignin.spring.data.dynamodb.utils.DynamoDBLocalResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.DirtiesContext.MethodMode;
import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.assertEquals;
-import org.junit.Ignore;
-
@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(classes = {CustomerHistoryIT.TestAppConfig.class, DynamoDBResource.class})
-@Ignore
-public class CustomerHistoryIT {
+@DirtiesContext(methodMode = MethodMode.BEFORE_METHOD)
+@ContextConfiguration(classes = {CustomerHistoryTest.TestAppConfig.class, DynamoDBLocalResource.class})
+@TestPropertySource(properties = {"spring.data.dynamodb.entity2ddl.auto=create"})
+public class CustomerHistoryTest {
@Configuration
@EnableDynamoDBRepositories(basePackages = "org.socialsignin.spring.data.dynamodb.domain.sample")
diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/core/DynamoDBTemplateIT.java b/src/test/java/org/socialsignin/spring/data/dynamodb/core/DynamoDBTemplateIT.java
index f5f24ec4..91499403 100755
--- a/src/test/java/org/socialsignin/spring/data/dynamodb/core/DynamoDBTemplateIT.java
+++ b/src/test/java/org/socialsignin/spring/data/dynamodb/core/DynamoDBTemplateIT.java
@@ -16,14 +16,17 @@
package org.socialsignin.spring.data.dynamodb.core;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.socialsignin.spring.data.dynamodb.domain.sample.User;
-import org.socialsignin.spring.data.dynamodb.utils.DynamoDBResource;
+import org.socialsignin.spring.data.dynamodb.utils.DynamoDBLocalResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.UUID;
@@ -32,17 +35,21 @@
* Integration test that interacts with DynamoDB Local instance.
*/
@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(classes = {DynamoDBResource.class})
-@Ignore
+@ContextConfiguration(classes = {DynamoDBLocalResource.class})
+@TestPropertySource(properties = {"spring.data.dynamodb.entity2ddl.auto=create"})
public class DynamoDBTemplateIT {
@Autowired
private AmazonDynamoDB amazonDynamoDB;
private DynamoDBTemplate dynamoDBTemplate;
+ @Autowired
+ private DynamoDBMapper mapper;
+ @Autowired
+ private DynamoDBMapperConfig mapperConfig;
@Before
public void setUp() {
- this.dynamoDBTemplate = new DynamoDBTemplate(amazonDynamoDB);
+ this.dynamoDBTemplate = new DynamoDBTemplate(amazonDynamoDB, mapper, mapperConfig);
}
@Test
diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/core/DynamoDBTemplateTest.java b/src/test/java/org/socialsignin/spring/data/dynamodb/core/DynamoDBTemplateTest.java
index cca003a2..e25ed1e7 100644
--- a/src/test/java/org/socialsignin/spring/data/dynamodb/core/DynamoDBTemplateTest.java
+++ b/src/test/java/org/socialsignin/spring/data/dynamodb/core/DynamoDBTemplateTest.java
@@ -18,7 +18,6 @@
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig;
-import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig.TableNameOverride;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBQueryExpression;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBScanExpression;
import org.junit.Assert;
@@ -32,14 +31,13 @@
import org.socialsignin.spring.data.dynamodb.domain.sample.Playlist;
import org.socialsignin.spring.data.dynamodb.domain.sample.User;
import org.springframework.context.ApplicationContext;
-import org.springframework.test.util.ReflectionTestUtils;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
@@ -52,6 +50,8 @@ public class DynamoDBTemplateTest {
@Mock
private DynamoDBMapper dynamoDBMapper;
@Mock
+ private DynamoDBMapperConfig dynamoDBMapperConfig;
+ @Mock
private AmazonDynamoDB dynamoDB;
@Mock
private ApplicationContext applicationContext;
@@ -62,30 +62,43 @@ public class DynamoDBTemplateTest {
@Before
public void setUp() {
- this.dynamoDBTemplate = new DynamoDBTemplate(dynamoDB, dynamoDBMapper);
+ this.dynamoDBTemplate = new DynamoDBTemplate(dynamoDB, dynamoDBMapper, dynamoDBMapperConfig);
this.dynamoDBTemplate.setApplicationContext(applicationContext);
- }
-
- @Test
- public void testConstructorMandatory() {
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("must not be null!");
- new DynamoDBTemplate(null);
- }
-
- @Test
- public void testConstructorOptionalAllNull() {
- dynamoDBTemplate = new DynamoDBTemplate(dynamoDB, null, null);
// check that the defaults are properly initialized - #108
String userTableName = dynamoDBTemplate.getOverriddenTableName(User.class, "UserTable");
- assertEquals("user", userTableName);
+ assertEquals("UserTable", userTableName);
}
+ @Test
+ public void testConstructorAllNull() {
+ try {
+ dynamoDBTemplate = new DynamoDBTemplate(null, null, null);
+ fail("AmazonDynamoDB must not be null!");
+ } catch (IllegalArgumentException iae) {
+ // ignored
+ }
+
+ try {
+ dynamoDBTemplate = new DynamoDBTemplate(dynamoDB, null, null);
+ fail("DynamoDBMapper must not be null!");
+ } catch (IllegalArgumentException iae) {
+ // ignored
+ }
+ try {
+ dynamoDBTemplate = new DynamoDBTemplate(dynamoDB, dynamoDBMapper, null);
+ fail("DynamoDBMapperConfig must not be null!");
+ } catch (IllegalArgumentException iae) {
+ // ignored
+ }
+ assertTrue(true);
+ }
+
+ // TODO remove and replace with postprocessor test
@Test
public void testConstructorOptionalPreconfiguredDynamoDBMapper() {
// Introduced constructor via #91 should not fail its assert
- new DynamoDBTemplate(dynamoDB, dynamoDBMapper);
+ this.dynamoDBTemplate = new DynamoDBTemplate(dynamoDB, dynamoDBMapper, dynamoDBMapperConfig);
assertTrue("The constructor should not fail with an assert error", true);
}
@@ -138,64 +151,6 @@ public void testCountScan() {
verify(dynamoDBMapper).count(User.class, scan);
}
- @Test
- public void testGetOverriddenTableName_WithTableNameResolver_defaultConfig() {
- final String overridenTableName = "someOtherTableName";
-
- DynamoDBMapperConfig.Builder builder = DynamoDBMapperConfig.builder();
- // Inject the table name overrider bean
- builder.setTableNameOverride(new TableNameOverride(overridenTableName));
-
- DynamoDBMapperConfig config = new DynamoDBMapperConfig(DynamoDBMapperConfig.DEFAULT, builder.build());
- DynamoDBTemplate tmpl = new DynamoDBTemplate(dynamoDB, config, dynamoDBMapper);
-
- String overriddenTableName = tmpl.getOverriddenTableName(User.class, "someTableName");
- assertEquals(overridenTableName, overriddenTableName);
-
- DynamoDBMapperConfig effectiveConfig = (DynamoDBMapperConfig) ReflectionTestUtils.getField(tmpl,
- "dynamoDBMapperConfig");
- assertDynamoDBMapperConfigCompletness(tmpl);
- }
-
- @Test
- public void testGetOverriddenTableName_WithTableNameResolver_defaultBuilder() {
- final String overridenTableName = "someOtherTableName";
-
- DynamoDBMapperConfig.Builder builder = new DynamoDBMapperConfig.Builder();
- // Inject the table name overrider bean
- builder.setTableNameOverride(new TableNameOverride(overridenTableName));
-
- DynamoDBTemplate tmpl = new DynamoDBTemplate(dynamoDB, builder.build(), dynamoDBMapper);
-
- String overriddenTableName = tmpl.getOverriddenTableName(User.class, "someTableName");
- assertEquals(overridenTableName, overriddenTableName);
- assertDynamoDBMapperConfigCompletness(tmpl);
- }
-
- @Test
- public void testGetOverriddenTableName_WithTableNameResolver_emptyBuilder() {
- final String overridenTableName = "someOtherTableName";
-
- DynamoDBMapperConfig.Builder builder = DynamoDBMapperConfig.builder();
- // Inject the table name overrider bean
- builder.setTableNameOverride(new TableNameOverride(overridenTableName));
-
- DynamoDBTemplate tmpl = new DynamoDBTemplate(dynamoDB, builder.build(), dynamoDBMapper);
-
- String overriddenTableName = tmpl.getOverriddenTableName(User.class, "someTableName");
- assertEquals(overridenTableName, overriddenTableName);
- assertDynamoDBMapperConfigCompletness(tmpl);
- }
-
- private void assertDynamoDBMapperConfigCompletness(DynamoDBTemplate tmpl) {
- DynamoDBMapperConfig effectiveConfig = (DynamoDBMapperConfig) ReflectionTestUtils.getField(tmpl,
- "dynamoDBMapperConfig");
-
- assertNotNull(effectiveConfig);
- assertNotNull(effectiveConfig.getConversionSchema());
- assertNotNull(effectiveConfig.getTypeConverterFactory());
- }
-
@Test
public void testLoadByHashKey_WhenDynamoDBMapperReturnsNull() {
User user = dynamoDBTemplate.load(User.class, "someHashKey");
diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/core/FeedUserIT.java b/src/test/java/org/socialsignin/spring/data/dynamodb/core/FeedUserIT.java
index 2837c35a..bec3d373 100644
--- a/src/test/java/org/socialsignin/spring/data/dynamodb/core/FeedUserIT.java
+++ b/src/test/java/org/socialsignin/spring/data/dynamodb/core/FeedUserIT.java
@@ -15,23 +15,23 @@
*/
package org.socialsignin.spring.data.dynamodb.core;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.socialsignin.spring.data.dynamodb.domain.sample.FeedUserRepository;
import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories;
-import org.socialsignin.spring.data.dynamodb.utils.DynamoDBResource;
+import org.socialsignin.spring.data.dynamodb.utils.DynamoDBLocalResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(classes = {FeedUserIT.TestAppConfig.class, DynamoDBResource.class})
-@Ignore
+@ContextConfiguration(classes = {FeedUserIT.TestAppConfig.class, DynamoDBLocalResource.class})
+@TestPropertySource(properties = {"spring.data.dynamodb.entity2ddl.auto=create"})
public class FeedUserIT {
@Configuration
diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/core/SortPageableIT.java b/src/test/java/org/socialsignin/spring/data/dynamodb/core/SortPageableIT.java
new file mode 100644
index 00000000..4f1ef6a8
--- /dev/null
+++ b/src/test/java/org/socialsignin/spring/data/dynamodb/core/SortPageableIT.java
@@ -0,0 +1,80 @@
+/**
+ * Copyright © 2018 spring-data-dynamodb (https://github.com/derjust/spring-data-dynamodb)
+ *
+ * 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.socialsignin.spring.data.dynamodb.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import java.time.LocalDateTime;
+import java.util.Random;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.socialsignin.spring.data.dynamodb.domain.sample.Feed;
+import org.socialsignin.spring.data.dynamodb.domain.sample.FeedPagingRepository;
+import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories;
+import org.socialsignin.spring.data.dynamodb.utils.DynamoDBLocalResource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = {SortPageableIT.TestAppConfig.class, DynamoDBLocalResource.class})
+@TestPropertySource(properties = {"spring.data.dynamodb.entity2ddl.auto=create"})
+public class SortPageableIT {
+ private final Random r = new Random();
+
+ @Configuration
+ @EnableDynamoDBRepositories(basePackages = "org.socialsignin.spring.data.dynamodb.domain.sample")
+ public static class TestAppConfig {
+ }
+
+ @Autowired
+ FeedPagingRepository feedPagingRepository;
+
+ private Feed createFeed(String message) {
+ Feed retValue = new Feed();
+ retValue.setUserIdx(r.nextInt());
+ retValue.setPaymentType(r.nextInt());
+ retValue.setMessage(message);
+ retValue.setRegDate(LocalDateTime.now());
+ return retValue;
+ }
+
+ @Test
+ public void feed_test() {
+ feedPagingRepository.save(createFeed("not yet me"));
+ feedPagingRepository.save(createFeed("me"));
+ feedPagingRepository.save(createFeed("not me"));
+ feedPagingRepository.save(createFeed("me"));
+ feedPagingRepository.save(createFeed("also not me"));
+
+ PageRequest pageable = PageRequest.of(0, 10);
+
+ Page actuals = feedPagingRepository.findAllByMessageOrderByRegDateDesc("me", pageable);
+ assertEquals(2, actuals.getTotalElements());
+
+ for (Feed actual : actuals) {
+ assertNotEquals(0, actual.getPaymentType());
+ assertNotEquals(0, actual.getUserIdx());
+ }
+
+ }
+}
diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/CRUDOperationsIT.java b/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/CRUDOperationsIT.java
index 132d6fba..9fe1db0f 100644
--- a/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/CRUDOperationsIT.java
+++ b/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/CRUDOperationsIT.java
@@ -15,11 +15,7 @@
*/
package org.socialsignin.spring.data.dynamodb.domain.sample;
-import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
-import com.amazonaws.services.dynamodbv2.document.Expected;
-
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
@@ -27,8 +23,6 @@
import org.junit.runner.RunWith;
import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories;
import org.socialsignin.spring.data.dynamodb.utils.DynamoDBLocalResource;
-import org.socialsignin.spring.data.dynamodb.utils.TableCreationListener;
-import org.socialsignin.spring.data.dynamodb.utils.TableCreationListener.DynamoDBCreateTable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.EmptyResultDataAccessException;
@@ -36,13 +30,12 @@
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.TestExecutionListeners;
+import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ThreadLocalRandom;
@@ -55,12 +48,10 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
-import static org.springframework.test.context.TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {DynamoDBLocalResource.class, CRUDOperationsIT.TestAppConfig.class})
-@TestExecutionListeners(listeners = TableCreationListener.class, mergeMode = MERGE_WITH_DEFAULTS)
-@DynamoDBCreateTable(entityClasses = {User.class, Playlist.class})
+@TestPropertySource(properties = {"spring.data.dynamodb.entity2ddl.auto=create"})
public class CRUDOperationsIT {
@Rule
diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/CustomerDocumentTest.java b/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/CustomerDocumentTest.java
index 24cb504e..78fffe0e 100644
--- a/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/CustomerDocumentTest.java
+++ b/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/CustomerDocumentTest.java
@@ -19,20 +19,17 @@
import org.junit.runner.RunWith;
import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories;
import org.socialsignin.spring.data.dynamodb.utils.DynamoDBLocalResource;
-import org.socialsignin.spring.data.dynamodb.utils.TableCreationListener;
-import org.socialsignin.spring.data.dynamodb.utils.TableCreationListener.DynamoDBCreateTable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.TestExecutionListeners;
+import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import static org.springframework.test.context.TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS;
-
@RunWith(SpringJUnit4ClassRunner.class)
+@DirtiesContext
@ContextConfiguration(classes = {DynamoDBLocalResource.class, CustomerDocumentTest.TestAppConfig.class})
-@TestExecutionListeners(listeners = TableCreationListener.class, mergeMode = MERGE_WITH_DEFAULTS)
-@DynamoDBCreateTable(entityClasses = {CustomerDocument.class})
+@TestPropertySource(properties = {"spring.data.dynamodb.entity2ddl.auto=create"})
public class CustomerDocumentTest {
@Configuration
diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/Feed.java b/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/Feed.java
new file mode 100644
index 00000000..53074f75
--- /dev/null
+++ b/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/Feed.java
@@ -0,0 +1,101 @@
+/**
+ * Copyright © 2018 spring-data-dynamodb (https://github.com/derjust/spring-data-dynamodb)
+ *
+ * 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.socialsignin.spring.data.dynamodb.domain.sample;
+
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAutoGeneratedKey;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBIndexHashKey;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBIndexRangeKey;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTypeConverted;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTypeConverter;
+import java.time.LocalDateTime;
+
+@DynamoDBTable(tableName = "gz_feed")
+public class Feed {
+ private String idx;
+ private int userIdx;
+ private String message;
+ private int paymentType;
+ private LocalDateTime regDate;
+
+ @DynamoDBHashKey
+ @DynamoDBAutoGeneratedKey
+ public String getIdx() {
+ return idx;
+ }
+
+ @DynamoDBAttribute
+ public int getUserIdx() {
+ return userIdx;
+ }
+
+ @DynamoDBAttribute
+ @DynamoDBIndexHashKey(globalSecondaryIndexName = "aaa")
+ public String getMessage() {
+ return message;
+ }
+
+ // @DynamoDBIndexRangeKey(attributeName = "PaymentType",
+ // globalSecondaryIndexName = "aaa")
+ @DynamoDBAttribute
+ public int getPaymentType() {
+ return paymentType;
+ }
+
+ @DynamoDBTypeConverted(converter = LocalDateTimeConverter.class)
+ @DynamoDBAttribute
+ @DynamoDBIndexRangeKey(globalSecondaryIndexName = "aaa")
+ public LocalDateTime getRegDate() {
+ return regDate;
+ }
+
+ public void setIdx(String idx) {
+ this.idx = idx;
+ }
+
+ public void setUserIdx(int userIdx) {
+ this.userIdx = userIdx;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public void setPaymentType(int paymentType) {
+ this.paymentType = paymentType;
+ }
+
+ public void setRegDate(LocalDateTime regDate) {
+ this.regDate = regDate;
+ }
+
+ static public class LocalDateTimeConverter implements DynamoDBTypeConverter {
+
+ @Override
+ public String convert(final LocalDateTime time) {
+
+ return time.toString();
+ }
+
+ @Override
+ public LocalDateTime unconvert(final String stringValue) {
+
+ return LocalDateTime.parse(stringValue);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/FeedPagingRepository.java b/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/FeedPagingRepository.java
new file mode 100644
index 00000000..6cd0e75d
--- /dev/null
+++ b/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/FeedPagingRepository.java
@@ -0,0 +1,28 @@
+/**
+ * Copyright © 2018 spring-data-dynamodb (https://github.com/derjust/spring-data-dynamodb)
+ *
+ * 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.socialsignin.spring.data.dynamodb.domain.sample;
+
+import org.socialsignin.spring.data.dynamodb.repository.DynamoDBPagingAndSortingRepository;
+import org.socialsignin.spring.data.dynamodb.repository.EnableScan;
+import org.socialsignin.spring.data.dynamodb.repository.EnableScanCount;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+
+@EnableScan
+@EnableScanCount
+public interface FeedPagingRepository extends DynamoDBPagingAndSortingRepository {
+ Page findAllByMessageOrderByRegDateDesc(String message, Pageable pageable);
+}
\ No newline at end of file
diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/GlobalSecondaryIndexWithRangeKeyIT.java b/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/GlobalSecondaryIndexWithRangeKeyIT.java
index fa1f3b49..27a48d66 100644
--- a/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/GlobalSecondaryIndexWithRangeKeyIT.java
+++ b/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/GlobalSecondaryIndexWithRangeKeyIT.java
@@ -15,14 +15,14 @@
*/
package org.socialsignin.spring.data.dynamodb.domain.sample;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories;
-import org.socialsignin.spring.data.dynamodb.utils.DynamoDBResource;
+import org.socialsignin.spring.data.dynamodb.utils.DynamoDBLocalResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.Calendar;
@@ -38,8 +38,8 @@
* Shows the usage of Hash+Range key combinations with global secondary indexes.
*/
@RunWith(SpringJUnit4ClassRunner.class)
-@Ignore
-@ContextConfiguration(classes = {DynamoDBResource.class, GlobalSecondaryIndexWithRangeKeyIT.TestAppConfig.class})
+@ContextConfiguration(classes = {DynamoDBLocalResource.class, GlobalSecondaryIndexWithRangeKeyIT.TestAppConfig.class})
+@TestPropertySource(properties = {"spring.data.dynamodb.entity2ddl.auto=create"})
public class GlobalSecondaryIndexWithRangeKeyIT {
@Configuration
diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/Jdk8IT.java b/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/Jdk8IT.java
index aeb1626f..99ba2160 100644
--- a/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/Jdk8IT.java
+++ b/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/Jdk8IT.java
@@ -15,14 +15,14 @@
*/
package org.socialsignin.spring.data.dynamodb.domain.sample;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories;
-import org.socialsignin.spring.data.dynamodb.utils.DynamoDBResource;
+import org.socialsignin.spring.data.dynamodb.utils.DynamoDBLocalResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.time.Instant;
@@ -30,7 +30,10 @@
import java.util.List;
import java.util.Optional;
import java.util.UUID;
-
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -42,8 +45,8 @@
* github.com/spring-projects/spring-data-examples/master/jpa/java8
*/
@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(classes = {DynamoDBResource.class, Jdk8IT.TestAppConfig.class})
-@Ignore
+@ContextConfiguration(classes = {DynamoDBLocalResource.class, Jdk8IT.TestAppConfig.class})
+@TestPropertySource(properties = {"spring.data.dynamodb.entity2ddl.auto=create"})
public class Jdk8IT {
@Configuration
@@ -76,6 +79,24 @@ public void testOptionalKey() {
assertEquals(joinDate, result.get().getJoinDate());
}
+ @Test
+ public void testFuture() throws InterruptedException, ExecutionException, TimeoutException {
+ User user = new User();
+ user.setName("testFuture");
+ user.setPostCode("postCode");
+ user = userRepository.save(user);
+
+ User actual;
+ // Future result
+ actual = userRepository.findByName("testFuture").get();
+ // assertNotNull(result);
+ // User actual = result.get(1, TimeUnit.MINUTES);
+
+ assertNotNull(actual);
+ assertNotNull(actual.getId());
+ assertEquals("postCode", actual.getPostCode());
+ }
+
@Test
public void testOptionalFilter() {
final Date joinDate = new Date(2000);
diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/User.java b/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/User.java
index ad77d903..e23daacf 100644
--- a/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/User.java
+++ b/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/User.java
@@ -15,7 +15,6 @@
*/
package org.socialsignin.spring.data.dynamodb.domain.sample;
-import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAutoGeneratedDefault;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAutoGeneratedKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBIndexHashKey;
diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/UserRepository.java b/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/UserRepository.java
index 086d2274..c30018fa 100644
--- a/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/UserRepository.java
+++ b/src/test/java/org/socialsignin/spring/data/dynamodb/domain/sample/UserRepository.java
@@ -22,6 +22,7 @@
import java.time.Instant;
import java.util.List;
import java.util.Optional;
+import java.util.concurrent.Future;
public interface UserRepository extends CrudRepository {
@@ -38,6 +39,11 @@ public interface UserRepository extends CrudRepository {
@EnableScan
Optional findByName(String name);
+ @EnableScan
+ Future findOneByPostCode(String postCode);
+ @EnableScan
+ User findFirstByPostCode(String postCode);
+
T save(T entity);
@EnableScan
diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/repository/config/DynamoDBMapperConfigFactoryTest.java b/src/test/java/org/socialsignin/spring/data/dynamodb/repository/config/DynamoDBMapperConfigFactoryTest.java
new file mode 100644
index 00000000..e168dad2
--- /dev/null
+++ b/src/test/java/org/socialsignin/spring/data/dynamodb/repository/config/DynamoDBMapperConfigFactoryTest.java
@@ -0,0 +1,97 @@
+/**
+ * Copyright © 2018 spring-data-dynamodb (https://github.com/derjust/spring-data-dynamodb)
+ *
+ * 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.socialsignin.spring.data.dynamodb.repository.config;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig.TableNameOverride;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+
+@RunWith(MockitoJUnitRunner.class)
+public class DynamoDBMapperConfigFactoryTest {
+
+ @Mock
+ private DynamoDBMapper dynamoDBMapper;
+ @Mock
+ private DynamoDBMapperConfig dynamoDBMapperConfig;
+ @Mock
+ private AmazonDynamoDB dynamoDB;
+
+ DynamoDBMapperConfigFactory underTest;
+
+ @Before
+ public void setUp() throws Exception {
+ underTest = new DynamoDBMapperConfigFactory();
+ }
+
+ @Test
+ public void testGetOverriddenTableName_WithTableNameResolver_defaultConfig() {
+
+ DynamoDBMapperConfig actual = (DynamoDBMapperConfig) underTest
+ .postProcessAfterInitialization(DynamoDBMapperConfig.DEFAULT, null);
+
+ assertSame(DynamoDBMapperConfig.DEFAULT, actual);
+ }
+
+ @Test
+ public void testGetOverriddenTableName_WithTableNameResolver_defaultBuilder() {
+ final String overridenTableName = "someOtherTableName";
+
+ DynamoDBMapperConfig.Builder builder = new DynamoDBMapperConfig.Builder();
+ // Inject the table name overrider bean
+ builder.setTableNameOverride(new TableNameOverride(overridenTableName));
+
+ DynamoDBMapperConfig actual = (DynamoDBMapperConfig) underTest.postProcessAfterInitialization(builder.build(),
+ null);
+
+ String overriddenTableName = actual.getTableNameOverride().getTableName();
+ assertEquals(overridenTableName, overriddenTableName);
+
+ assertDynamoDBMapperConfigCompletness(actual);
+ }
+
+ @Test
+ public void testGetOverriddenTableName_WithTableNameResolver_emptyBuilder() {
+ final String overridenTableName = "someOtherTableName";
+
+ DynamoDBMapperConfig.Builder builder = DynamoDBMapperConfig.builder();
+ // Inject the table name overrider bean
+ builder.setTableNameOverride(new TableNameOverride(overridenTableName));
+
+ DynamoDBMapperConfig actual = (DynamoDBMapperConfig) underTest.postProcessAfterInitialization(builder.build(),
+ null);
+
+ String overriddenTableName = actual.getTableNameOverride().getTableName();
+ assertEquals(overridenTableName, overriddenTableName);
+
+ assertDynamoDBMapperConfigCompletness(actual);
+ }
+
+ private void assertDynamoDBMapperConfigCompletness(DynamoDBMapperConfig effectiveConfig) {
+ assertNotNull(effectiveConfig);
+ assertNotNull(effectiveConfig.getConversionSchema());
+ assertNotNull(effectiveConfig.getTypeConverterFactory());
+ }
+
+}
diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/repository/support/DynamoDBRepositoryFactoryBeanTest.java b/src/test/java/org/socialsignin/spring/data/dynamodb/repository/support/DynamoDBRepositoryFactoryBeanTest.java
index 4d14bf35..2aa00671 100644
--- a/src/test/java/org/socialsignin/spring/data/dynamodb/repository/support/DynamoDBRepositoryFactoryBeanTest.java
+++ b/src/test/java/org/socialsignin/spring/data/dynamodb/repository/support/DynamoDBRepositoryFactoryBeanTest.java
@@ -26,6 +26,8 @@
import org.socialsignin.spring.data.dynamodb.core.DynamoDBOperations;
import org.socialsignin.spring.data.dynamodb.domain.sample.User;
import org.socialsignin.spring.data.dynamodb.mapping.DynamoDBMappingContext;
+import org.socialsignin.spring.data.dynamodb.repository.util.DynamoDBMappingContextProcessor;
+import org.socialsignin.spring.data.dynamodb.repository.util.Entity2DynamoDBTableSynchronizer;
import org.springframework.context.ApplicationContext;
import org.springframework.data.repository.Repository;
@@ -45,6 +47,10 @@ public class DynamoDBRepositoryFactoryBeanTest {
private DynamoDBMapperConfig dynamoDBMapperConfig;
@Mock
private AmazonDynamoDB amazonDynamoDB;
+ @Mock
+ private Entity2DynamoDBTableSynchronizer tableSynchronizer;
+ @Mock
+ private DynamoDBMappingContextProcessor dynamoDBMappingContextProcessor;
private DynamoDBMappingContext dynamoDBMappingContext = new DynamoDBMappingContext();
@@ -57,9 +63,9 @@ public interface UserRepository extends Repository {
@Before
public void setUp() {
underTest = spy(new DynamoDBRepositoryFactoryBean<>(UserRepository.class));
- underTest.setApplicationContext(applicationContext);
- underTest.setDynamoDBMapperConfig(dynamoDBMapperConfig);
underTest.setDynamoDBMappingContext(dynamoDBMappingContext);
+ underTest.setEntity2DynamoDBTableSynchronizer(tableSynchronizer);
+ underTest.setDynamoDBMappingContextProcessor(dynamoDBMappingContextProcessor);
}
@Test
@@ -86,7 +92,7 @@ public void testAmazonDynamoDB() {
assertTrue(true);
}
- underTest.setAmazonDynamoDB(amazonDynamoDB);
+ underTest.setDynamoDBOperations(dynamoDBOperations);
underTest.afterPropertiesSet();
assertNotNull(underTest.getPersistentEntity());
diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/repository/util/Entity2DDLTest.java b/src/test/java/org/socialsignin/spring/data/dynamodb/repository/util/Entity2DDLTest.java
new file mode 100644
index 00000000..a53d8667
--- /dev/null
+++ b/src/test/java/org/socialsignin/spring/data/dynamodb/repository/util/Entity2DDLTest.java
@@ -0,0 +1,42 @@
+/**
+ * Copyright © 2018 spring-data-dynamodb (https://github.com/derjust/spring-data-dynamodb)
+ *
+ * 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.socialsignin.spring.data.dynamodb.repository.util;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import static org.junit.Assert.assertEquals;
+
+public class Entity2DDLTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Test
+ public void testFromExistingValue() {
+ Entity2DDL actual = Entity2DDL.fromValue(Entity2DDL.NONE.getConfigurationValue());
+
+ assertEquals(Entity2DDL.NONE, actual);
+ }
+
+ @Test
+ public void testFromNotExistingValue() {
+ expectedException.expect(IllegalArgumentException.class);
+
+ Entity2DDL.fromValue("doesnt exist");
+ }
+
+}
diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/repository/util/Entity2DynamoDBTableSynchronizerTest.java b/src/test/java/org/socialsignin/spring/data/dynamodb/repository/util/Entity2DynamoDBTableSynchronizerTest.java
new file mode 100644
index 00000000..953fdb0b
--- /dev/null
+++ b/src/test/java/org/socialsignin/spring/data/dynamodb/repository/util/Entity2DynamoDBTableSynchronizerTest.java
@@ -0,0 +1,162 @@
+/**
+ * Copyright © 2018 spring-data-dynamodb (https://github.com/derjust/spring-data-dynamodb)
+ *
+ * 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.socialsignin.spring.data.dynamodb.repository.util;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBEntityInformation;
+import org.socialsignin.spring.data.dynamodb.repository.support.SimpleDynamoDBCrudRepository;
+import org.springframework.aop.TargetSource;
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.event.ContextClosedEvent;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.context.event.ContextStoppedEvent;
+import org.springframework.data.repository.core.RepositoryInformation;
+import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
+import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
+import com.amazonaws.services.dynamodbv2.model.DeleteTableRequest;
+import com.amazonaws.services.dynamodbv2.model.DescribeTableRequest;
+import com.amazonaws.services.dynamodbv2.model.DescribeTableResult;
+import com.amazonaws.services.dynamodbv2.model.TableDescription;
+import com.amazonaws.services.dynamodbv2.model.TableStatus;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class Entity2DynamoDBTableSynchronizerTest {
+
+ private Entity2DynamoDBTableSynchronizer underTest;
+ @Mock
+ private AmazonDynamoDB amazonDynamoDB;
+ @Mock
+ private DynamoDBMapper mapper;
+ @Mock
+ private ProxyFactory factory;
+ @Mock
+ private RepositoryInformation repositoryInformation;
+ @Mock
+ private ApplicationContext applicationContext;
+ @Mock
+ private SimpleDynamoDBCrudRepository repository;
+ @Mock
+ private DynamoDBEntityInformation entityInformation;
+
+ @Before
+ public void setUp() throws Exception {
+ TargetSource targetSource = mock(TargetSource.class);
+ when(targetSource.getTarget()).thenReturn(repository);
+ when(factory.getTargetSource()).thenReturn(targetSource);
+
+ when(repository.getEntityInformation()).thenReturn(entityInformation);
+
+ when(entityInformation.getDynamoDBTableName()).thenReturn("tableName");
+
+ CreateTableRequest ctr = mock(CreateTableRequest.class);
+ when(mapper.generateCreateTableRequest(any())).thenReturn(ctr);
+ DeleteTableRequest dtr = mock(DeleteTableRequest.class);
+ when(mapper.generateDeleteTableRequest(any())).thenReturn(dtr);
+
+ DescribeTableResult describeResult = mock(DescribeTableResult.class);
+ TableDescription description = mock(TableDescription.class);
+ when(description.getTableStatus()).thenReturn(TableStatus.ACTIVE.toString());
+ when(describeResult.getTable()).thenReturn(description);
+ when(amazonDynamoDB.describeTable(any(DescribeTableRequest.class))).thenReturn(describeResult);
+ }
+
+ public void setUp(Entity2DDL mode) {
+ underTest = new Entity2DynamoDBTableSynchronizer<>(amazonDynamoDB, mapper, mode);
+ underTest.postProcess(factory, repositoryInformation);
+ }
+
+ public void runContextStart() {
+ underTest.onApplicationEvent(new ContextRefreshedEvent(applicationContext));
+ }
+
+ public void runContextStop() {
+ underTest.onApplicationEvent(new ContextStoppedEvent(applicationContext));
+ }
+
+ @Test
+ public void testUnmatchedEvent() {
+ setUp(Entity2DDL.NONE);
+
+ underTest.onApplicationEvent(new ContextClosedEvent(applicationContext));
+
+ verify(factory).getTargetSource();
+ verifyNoMoreInteractions(amazonDynamoDB, mapper, factory, repositoryInformation, applicationContext);
+ }
+
+ @Test
+ public void testNone() {
+ setUp(Entity2DDL.NONE);
+
+ runContextStart();
+
+ runContextStop();
+
+ verify(factory).getTargetSource();
+ verifyNoMoreInteractions(amazonDynamoDB, mapper, factory, repositoryInformation, applicationContext);
+
+ }
+
+ @Test
+ public void testCreate() {
+ setUp(Entity2DDL.CREATE);
+
+ runContextStart();
+ verify(amazonDynamoDB).deleteTable(any(DeleteTableRequest.class));
+ verify(amazonDynamoDB).createTable(any());
+ verify(amazonDynamoDB).describeTable(any(DescribeTableRequest.class));
+
+ runContextStop();
+ verify(amazonDynamoDB).deleteTable(any(DeleteTableRequest.class));
+ verifyNoMoreInteractions(amazonDynamoDB);
+ }
+
+ @Test
+ public void testDrop() {
+ setUp(Entity2DDL.DROP);
+
+ runContextStart();
+
+ runContextStop();
+ }
+
+ @Test
+ public void testCreateOnly() {
+ setUp(Entity2DDL.CREATE_ONLY);
+
+ runContextStart();
+ verify(amazonDynamoDB).createTable(any());
+ verify(amazonDynamoDB).describeTable(any(DescribeTableRequest.class));
+
+ runContextStop();
+ verifyNoMoreInteractions(amazonDynamoDB);
+ }
+
+ @Test
+ public void testCreateDrop() {
+ setUp(Entity2DDL.CREATE_DROP);
+
+ runContextStart();
+
+ runContextStop();
+ }
+}
diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/utils/TableCreationListener.java b/src/test/java/org/socialsignin/spring/data/dynamodb/utils/TableCreationListener.java
deleted file mode 100644
index 376ae538..00000000
--- a/src/test/java/org/socialsignin/spring/data/dynamodb/utils/TableCreationListener.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/**
- * Copyright © 2018 spring-data-dynamodb (https://github.com/derjust/spring-data-dynamodb)
- *
- * 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.socialsignin.spring.data.dynamodb.utils;
-
-import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
-import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
-import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
-import com.amazonaws.services.dynamodbv2.model.CreateTableResult;
-import com.amazonaws.services.dynamodbv2.model.Projection;
-import com.amazonaws.services.dynamodbv2.model.ProjectionType;
-import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
-import org.springframework.beans.factory.BeanFactory;
-import org.springframework.test.context.TestContext;
-import org.springframework.test.context.support.AbstractTestExecutionListener;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.util.Arrays;
-
-public class TableCreationListener extends AbstractTestExecutionListener {
-
- public static CreateTableResult createTable(AmazonDynamoDB ddb, Class domainType) {
- DynamoDBMapper mapper = new DynamoDBMapper(ddb);
-
- ProvisionedThroughput pt = new ProvisionedThroughput(10L, 10L);
-
- CreateTableRequest ctr = mapper.generateCreateTableRequest(domainType);
- ctr.setProvisionedThroughput(pt);
- if (ctr.getGlobalSecondaryIndexes() != null) {
- ctr.getGlobalSecondaryIndexes().forEach(gsi -> {
- gsi.setProjection(new Projection().withProjectionType(ProjectionType.ALL));
- gsi.setProvisionedThroughput(pt);
- });
- }
-
- CreateTableResult ctResponse = ddb.createTable(ctr);
-
- do {
- try {
- Thread.sleep(1 * 1000L);
- } catch (InterruptedException e) {
- throw new RuntimeException("Couldn't wait detect table " + ctr.getTableName());
- }
- } while (!ddb.describeTable(ctr.getTableName()).getTable().getTableStatus().equals("ACTIVE"));
-
- return ctResponse;
- }
-
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.TYPE)
- @Documented
- public @interface DynamoDBCreateTable {
- Class>[] entityClasses();
- }
-
- protected Class>[] getEntityClasses() {
- return new Class>[0];
- }
-
- private void createExpliclitEntities(TestContext testContext) {
- BeanFactory bf = testContext.getApplicationContext().getAutowireCapableBeanFactory();
-
- AmazonDynamoDB ddb = bf.getBean(AmazonDynamoDB.class);
-
- Arrays.stream(getEntityClasses()).forEach(clazz -> createTable(ddb, clazz));
- }
-
- @Override
- public void beforeTestClass(TestContext testContext) {
- createExpliclitEntities(testContext);
- createAnnotationEntities(testContext);
- }
-
- private void createAnnotationEntities(TestContext testContext) {
-
- Class> testClass = testContext.getTestClass();
- if (testClass.isAnnotationPresent(DynamoDBCreateTable.class)) {
-
- DynamoDBCreateTable createTableAnnotation = testClass.getAnnotation(DynamoDBCreateTable.class);
-
- AmazonDynamoDB ddb = getAmazonDynamoDB(testContext);
-
- for (Class> entityClass : createTableAnnotation.entityClasses()) {
- createTable(ddb, entityClass);
- }
- }
- }
-
- @Override
- public void afterTestClass(TestContext testContext) throws Exception {
- getAmazonDynamoDB(testContext).shutdown();
- }
-
- private BeanFactory getBeanFactory(TestContext testContext) {
- return testContext.getApplicationContext().getAutowireCapableBeanFactory();
- }
-
- private AmazonDynamoDB getAmazonDynamoDB(TestContext testContext) {
- return getBeanFactory(testContext).getBean(AmazonDynamoDB.class);
- }
-}
diff --git a/src/test/resources/auditable_user_table.json b/src/test/resources/auditable_user_table.json
deleted file mode 100644
index b8406598..00000000
--- a/src/test/resources/auditable_user_table.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "AttributeDefinitions": [
- {
- "AttributeName": "id",
- "AttributeType": "S"
- }
- ],
- "KeySchema": [
- {
- "AttributeName": "id",
- "KeyType": "HASH"
- }
- ],
- "ProvisionedThroughput": {
- "ReadCapacityUnits": "10",
- "WriteCapacityUnits": "10"
- },
- "TableName": "auditableUser"
-}
\ No newline at end of file
diff --git a/src/test/resources/customerhistory_table.json b/src/test/resources/customerhistory_table.json
deleted file mode 100644
index 7e239f5a..00000000
--- a/src/test/resources/customerhistory_table.json
+++ /dev/null
@@ -1,49 +0,0 @@
-{
- "AttributeDefinitions": [
- {
- "AttributeName": "customerId",
- "AttributeType": "S"
- },
- {
- "AttributeName": "createDt",
- "AttributeType": "S"
- },
- {
- "AttributeName": "tag",
- "AttributeType": "S"
- }
- ],
- "KeySchema": [
- {
- "AttributeName": "customerId",
- "KeyType": "HASH"
- },
- {
- "AttributeName": "createDt",
- "KeyType": "RANGE"
- }
- ],
- "ProvisionedThroughput": {
- "ReadCapacityUnits": "10",
- "WriteCapacityUnits": "10"
- },
- "GlobalSecondaryIndexes": [
- {
- "IndexName": "idx_global_tag",
- "KeySchema": [
- {
- "AttributeName": "tag",
- "KeyType": "HASH"
- }
- ],
- "Projection": {
- "ProjectionType": "ALL"
- },
- "ProvisionedThroughput": {
- "ReadCapacityUnits": 10,
- "WriteCapacityUnits": 10
- }
- }
- ],
- "TableName": "customerhistory"
-}
diff --git a/src/test/resources/feeduser_table.json b/src/test/resources/feeduser_table.json
deleted file mode 100755
index 6fa99932..00000000
--- a/src/test/resources/feeduser_table.json
+++ /dev/null
@@ -1,50 +0,0 @@
-{
- "AttributeDefinitions": [
- {
- "AttributeName": "id",
- "AttributeType": "S"
- },
- {
- "AttributeName": "usrNo",
- "AttributeType": "N"
- },
- {
- "AttributeName": "feedOpenYn",
- "AttributeType": "N"
- }
- ],
- "KeySchema": [
- {
- "AttributeName": "id",
- "KeyType": "HASH"
- }
- ],
- "ProvisionedThroughput": {
- "ReadCapacityUnits": "10",
- "WriteCapacityUnits": "10"
- },
- "GlobalSecondaryIndexes": [
- {
- "IndexName": "idx_global_usrNo_feedOpenYn",
- "KeySchema": [
- {
- "AttributeName": "usrNo",
- "KeyType": "HASH"
- },
- {
- "AttributeName": "feedOpenYn",
- "KeyType": "RANGE"
- }
-
- ],
- "Projection": {
- "ProjectionType": "ALL"
- },
- "ProvisionedThroughput": {
- "ReadCapacityUnits": 10,
- "WriteCapacityUnits": 10
- }
- }
- ],
- "TableName": "feed_user"
-}
diff --git a/src/test/resources/installation_table.json b/src/test/resources/installation_table.json
deleted file mode 100644
index 7bb1fb14..00000000
--- a/src/test/resources/installation_table.json
+++ /dev/null
@@ -1,49 +0,0 @@
-{
- "AttributeDefinitions": [
- {
- "AttributeName": "id",
- "AttributeType": "S"
- },
- {
- "AttributeName": "systemId",
- "AttributeType": "S"
- },
- {
- "AttributeName": "updatedAt",
- "AttributeType": "S"
- }
- ],
- "KeySchema": [
- {
- "AttributeName": "id",
- "KeyType": "HASH"
- }
- ],
- "ProvisionedThroughput": {
- "ReadCapacityUnits": "1",
- "WriteCapacityUnits": "1"
- },
- "GlobalSecondaryIndexes": [
- {
- "IndexName": "idx-global-systemid",
- "KeySchema": [
- {
- "AttributeName": "systemId",
- "KeyType": "HASH"
- },
- {
- "AttributeName": "updatedAt",
- "KeyType": "RANGE"
- }
- ],
- "Projection": {
- "ProjectionType": "ALL"
- },
- "ProvisionedThroughput": {
- "ReadCapacityUnits": 1,
- "WriteCapacityUnits": 1
- }
- }
- ],
- "TableName": "installations"
-}
diff --git a/src/test/resources/playlist_table.json b/src/test/resources/playlist_table.json
deleted file mode 100755
index 14ab1d91..00000000
--- a/src/test/resources/playlist_table.json
+++ /dev/null
@@ -1,27 +0,0 @@
-{
- "AttributeDefinitions": [
- {
- "AttributeName": "UserName",
- "AttributeType": "S"
- },
- {
- "AttributeName": "PlaylistName",
- "AttributeType": "S"
- }
- ],
- "KeySchema": [
- {
- "AttributeName": "UserName",
- "KeyType": "HASH"
- },
- {
- "AttributeName": "PlaylistName",
- "KeyType": "RANGE"
- }
- ],
- "ProvisionedThroughput": {
- "ReadCapacityUnits": "10",
- "WriteCapacityUnits": "10"
- },
- "TableName": "playlist"
-}
\ No newline at end of file
diff --git a/src/test/resources/user_table.json b/src/test/resources/user_table.json
deleted file mode 100755
index efe6b2e5..00000000
--- a/src/test/resources/user_table.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "AttributeDefinitions": [
- {
- "AttributeName": "Id",
- "AttributeType": "S"
- }
- ],
- "KeySchema": [
- {
- "AttributeName": "Id",
- "KeyType": "HASH"
- }
- ],
- "ProvisionedThroughput": {
- "ReadCapacityUnits": "10",
- "WriteCapacityUnits": "10"
- },
- "TableName": "user"
-}
\ No newline at end of file