From 917c660252bf0e76ab234efe96d5f4b8db7280fa Mon Sep 17 00:00:00 2001 From: Sebastian J Date: Tue, 23 Jan 2018 00:36:52 -0500 Subject: [PATCH 1/2] Local Unit testing with real DynamoDB Provides `@Configurable` annotation for JUnit tests to bootstrap a (in-memory) DynamoDB database for real-life testing of AWS SDK calls. By no means should this replace the TI tests that aim for the standalon DynamoDB integration testing! --- pom.xml | 118 ++++++++++++++++++ .../data/dynamodb/core/CustomerHistoryIT.java | 3 +- .../dynamodb/core/DynamoDBTemplateIT.java | 3 +- .../spring/data/dynamodb/core/FeedUserIT.java | 3 +- .../GlobalSecondaryIndexWithRangeKeyIT.java | 4 +- .../data/dynamodb/domain/sample/Jdk8IT.java | 4 +- .../dynamodb/utils/DynamoDBLocalResource.java | 85 +++++++++++++ .../DynamoDBResource.java} | 15 ++- 8 files changed, 223 insertions(+), 12 deletions(-) create mode 100644 src/test/java/org/socialsignin/spring/data/dynamodb/utils/DynamoDBLocalResource.java rename src/test/java/org/socialsignin/spring/data/dynamodb/{core/ConfigurationTI.java => utils/DynamoDBResource.java} (69%) diff --git a/pom.xml b/pom.xml index 03f56a66..ce918878 100755 --- a/pom.xml +++ b/pom.xml @@ -46,6 +46,7 @@ 1.2 1.2.0 + 1.0.392 UTF-8 UTF-8 @@ -97,6 +98,12 @@ import + + com.amazonaws + DynamoDBLocal + [1.11,2.0) + + uk.org.lidalia slf4j-test @@ -153,6 +160,11 @@ spring-test test + + com.amazonaws + DynamoDBLocal + test + junit junit @@ -411,6 +423,43 @@ + + org.apache.maven.plugins + maven-dependency-plugin + + + copy + test-compile + + copy + + + + + com.almworks.sqlite4java + ${sqlite4java.artifactId} + ${sqlite4java.version} + ${sqlite4java.type} + true + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + + sqlite4java.library.path + ${project.build.directory}/lib + + + + org.apache.maven.plugins maven-failsafe-plugin @@ -444,6 +493,11 @@ spring-libs-snapshot http://repo.springsource.org/libs-snapshot + + dynamodb-local-oregon + DynamoDB Local Release Repository + https://s3-us-west-2.amazonaws.com/dynamodb-local/release + @@ -457,6 +511,70 @@ + + mac + + + mac + + + + libsqlite4java-osx + dylib + + + + linux-x32 + + + unix + i386 + + + + libsqlite4java-linux-i386 + so + + + + linux-x64 + + + unix + amd64 + + + + libsqlite4java-linux-amd64 + so + + + + windows-x86 + + + windows + x86 + + + + libsqlite4java-win32-x86 + dll + + + + windows-x64 + + + windows + x64 + + + + libsqlite4java-win32-x64 + dll + + release diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/core/CustomerHistoryIT.java b/src/test/java/org/socialsignin/spring/data/dynamodb/core/CustomerHistoryIT.java index 96975665..ad3b2263 100644 --- a/src/test/java/org/socialsignin/spring/data/dynamodb/core/CustomerHistoryIT.java +++ b/src/test/java/org/socialsignin/spring/data/dynamodb/core/CustomerHistoryIT.java @@ -20,6 +20,7 @@ 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.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.ContextConfiguration; @@ -29,7 +30,7 @@ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes={CustomerHistoryIT.TestAppConfig.class, ConfigurationTI.class}) +@ContextConfiguration(classes={CustomerHistoryIT.TestAppConfig.class, DynamoDBResource.class}) public class CustomerHistoryIT { @Configuration 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 35b42f15..874fa799 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 @@ -20,6 +20,7 @@ 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.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -30,7 +31,7 @@ * Integration test that interacts with DynamoDB Local instance. */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes={ConfigurationTI.class}) +@ContextConfiguration(classes={DynamoDBResource.class}) public class DynamoDBTemplateIT { @Autowired 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 4ec833fd..80682415 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 @@ -19,6 +19,7 @@ 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.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.data.domain.PageRequest; @@ -28,7 +29,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes={FeedUserIT.TestAppConfig.class, ConfigurationTI.class}) +@ContextConfiguration(classes={FeedUserIT.TestAppConfig.class, DynamoDBResource.class}) public class FeedUserIT { @Configuration 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 ca7d2888..c8a926b7 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 @@ -17,8 +17,8 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.socialsignin.spring.data.dynamodb.core.ConfigurationTI; import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories; +import org.socialsignin.spring.data.dynamodb.utils.DynamoDBResource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.ContextConfiguration; @@ -38,7 +38,7 @@ * Shows the usage of Hash+Range key combinations with global secondary indexes. */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = {ConfigurationTI.class, GlobalSecondaryIndexWithRangeKeyIT.TestAppConfig.class}) +@ContextConfiguration(classes = {DynamoDBResource.class, GlobalSecondaryIndexWithRangeKeyIT.TestAppConfig.class}) 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 2e07eb19..76440d27 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 @@ -17,8 +17,8 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.socialsignin.spring.data.dynamodb.core.ConfigurationTI; import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories; +import org.socialsignin.spring.data.dynamodb.utils.DynamoDBResource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.ContextConfiguration; @@ -39,7 +39,7 @@ * github.com/spring-projects/spring-data-examples/master/jpa/java8 */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = {ConfigurationTI.class, Jdk8IT.TestAppConfig.class}) +@ContextConfiguration(classes = {DynamoDBResource.class, Jdk8IT.TestAppConfig.class}) public class Jdk8IT { @Configuration diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/utils/DynamoDBLocalResource.java b/src/test/java/org/socialsignin/spring/data/dynamodb/utils/DynamoDBLocalResource.java new file mode 100644 index 00000000..f704c15b --- /dev/null +++ b/src/test/java/org/socialsignin/spring/data/dynamodb/utils/DynamoDBLocalResource.java @@ -0,0 +1,85 @@ +/** + * Copyright © 2013 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.local.embedded.DynamoDBEmbedded; +import com.amazonaws.services.dynamodbv2.model.AttributeDefinition; +import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; +import com.amazonaws.services.dynamodbv2.model.CreateTableResult; +import com.amazonaws.services.dynamodbv2.model.KeySchemaElement; +import com.amazonaws.services.dynamodbv2.model.KeyType; +import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; +import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType; +import org.junit.rules.ExternalResource; +import org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBEntityMetadataSupport; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.ArrayList; +import java.util.List; + +@Configuration +public class DynamoDBLocalResource extends ExternalResource { + + private AmazonDynamoDB ddb; + + @Bean + public AmazonDynamoDB amazonDynamoDB() { + ddb = DynamoDBEmbedded.create().amazonDynamoDB(); + return ddb; + } + + public CreateTableResult createTable(Class domainType) { + DynamoDBEntityMetadataSupport support = new DynamoDBEntityMetadataSupport(domainType); + + String tableName = support.getDynamoDBTableName(); + String hashKey = support.getHashKeyPropertyName(); + String rangeKey = support.getHashKeyPropertyName(); + + return createTable(tableName, hashKey, rangeKey); + } + + private CreateTableResult createTable(String tableName, String hashKeyName, String rangeKeyName) { + List attributeDefinitions = new ArrayList<>(); + attributeDefinitions.add(new AttributeDefinition(hashKeyName, ScalarAttributeType.S)); + + List ks = new ArrayList<>(); + ks.add(new KeySchemaElement(hashKeyName, KeyType.HASH)); + + if (rangeKeyName != null) { + attributeDefinitions.add(new AttributeDefinition(rangeKeyName, ScalarAttributeType.S)); + + ks.add(new KeySchemaElement(rangeKeyName, KeyType.RANGE)); + } + + ProvisionedThroughput provisionedthroughput = new ProvisionedThroughput(10L, 10L); + + CreateTableRequest request = + new CreateTableRequest() + .withTableName(tableName) + .withAttributeDefinitions(attributeDefinitions) + .withKeySchema(ks) + .withProvisionedThroughput(provisionedthroughput); + + return ddb.createTable(request); + } + + @Override + protected void after() { + ddb.shutdown(); + }; +} diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/core/ConfigurationTI.java b/src/test/java/org/socialsignin/spring/data/dynamodb/utils/DynamoDBResource.java similarity index 69% rename from src/test/java/org/socialsignin/spring/data/dynamodb/core/ConfigurationTI.java rename to src/test/java/org/socialsignin/spring/data/dynamodb/utils/DynamoDBResource.java index a49f53bd..dc48a867 100644 --- a/src/test/java/org/socialsignin/spring/data/dynamodb/core/ConfigurationTI.java +++ b/src/test/java/org/socialsignin/spring/data/dynamodb/utils/DynamoDBResource.java @@ -13,11 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.socialsignin.spring.data.dynamodb.core; +package org.socialsignin.spring.data.dynamodb.utils; +import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.client.builder.AwsClientBuilder; import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; +import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.Assert; @@ -28,7 +31,7 @@ * launched local DynamoDB by Maven's integration-test. */ @Configuration -public class ConfigurationTI { +public class DynamoDBResource { private static final String DYNAMODB_PORT_PROPERTY = "dynamodb.port"; private static final String PORT = System.getProperty(DYNAMODB_PORT_PROPERTY); @@ -36,9 +39,11 @@ public class ConfigurationTI { public AmazonDynamoDB amazonDynamoDB() { Assert.notNull(PORT, "System property '" + DYNAMODB_PORT_PROPERTY + " not set!"); - AmazonDynamoDB dynamoDB = new AmazonDynamoDBClient(new BasicAWSCredentials("AWS-Key", "")); - dynamoDB.setEndpoint(String.format("http://localhost:%s", PORT)); + AmazonDynamoDBClientBuilder builder = AmazonDynamoDBClientBuilder.standard(); + builder.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("AWS-Key", ""))); + builder.withEndpointConfiguration( + new AwsClientBuilder.EndpointConfiguration(String.format("http://localhost:%s", PORT), "us-east-1")); - return dynamoDB; + return builder.build(); } } From f77b4f14dabdc6163bcf27ba593d85c2901476bd Mon Sep 17 00:00:00 2001 From: Sebastian J Date: Sun, 14 Jan 2018 04:25:36 -0500 Subject: [PATCH 2/2] Issue #114: Scanning by nested properties --- pom.xml | 1 + src/changes/changes.xml | 2 +- .../query/AbstractDynamoDBQueryCreator.java | 15 +++-- .../DynamoDBEntityMetadataSupport.java | 8 +-- .../repository/query/nested/Address.java | 37 +++++++++++ .../query/nested/NestedPropertiesTest.java | 59 +++++++++++++++++ .../repository/query/nested/Person.java | 65 +++++++++++++++++++ .../repository/query/nested/PersonId.java | 53 +++++++++++++++ .../query/nested/PersonRepository.java | 36 ++++++++++ src/test/resources/person_table.json | 27 ++++++++ 10 files changed, 294 insertions(+), 9 deletions(-) create mode 100644 src/test/java/org/socialsignin/spring/data/dynamodb/repository/query/nested/Address.java create mode 100644 src/test/java/org/socialsignin/spring/data/dynamodb/repository/query/nested/NestedPropertiesTest.java create mode 100644 src/test/java/org/socialsignin/spring/data/dynamodb/repository/query/nested/Person.java create mode 100644 src/test/java/org/socialsignin/spring/data/dynamodb/repository/query/nested/PersonId.java create mode 100644 src/test/java/org/socialsignin/spring/data/dynamodb/repository/query/nested/PersonRepository.java create mode 100755 src/test/resources/person_table.json diff --git a/pom.xml b/pom.xml index ce918878..c146f6dd 100755 --- a/pom.xml +++ b/pom.xml @@ -399,6 +399,7 @@ src/test/resources/customerhistory_table.json
src/test/resources/installation_table.json
src/test/resources/auditable_user_table.json
+ src/test/resources/person_table.json
${dynamodblocal.port} ${project.build.directory}/dynamodb-dist diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 18795796..8349c6f3 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -20,7 +20,7 @@ xsi:schemaLocation="http://maven.apache.org/changes/1.0.0 http://maven.apache.org/xsd/changes-1.0.0.xsd"> spring-data-dynamodb Changes - derjust + derjust diff --git a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/query/AbstractDynamoDBQueryCreator.java b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/query/AbstractDynamoDBQueryCreator.java index ae004fbb..fcde3d48 100644 --- a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/query/AbstractDynamoDBQueryCreator.java +++ b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/query/AbstractDynamoDBQueryCreator.java @@ -71,14 +71,21 @@ protected DynamoDBQueryCriteria addCriteria(DynamoDBQueryCriteria throw new UnsupportedOperationException("Case insensitivity not supported"); Class leafNodePropertyType = part.getProperty().getLeafProperty().getType(); - - PropertyPath leafNodePropertyPath = part.getProperty().getLeafProperty(); - String leafNodePropertyName = leafNodePropertyPath.toDotPath(); + + part.getProperty().forEach(System.out::println); + + //PropertyPath leafNodePropertyPath = part.getProperty().getLeafProperty(); + //String leafNodePropertyName = leafNodePropertyPath.toDotPath(); + String leafNodePropertyName = part.getProperty().toDotPath(); + //TODO #114 - is this correct? + //TODO max deepth of 32 supported by AWS + /* if (leafNodePropertyName.indexOf(".") != -1) { + int index = leafNodePropertyName.lastIndexOf("."); leafNodePropertyName = leafNodePropertyName.substring(index); - } + }*/ switch (part.getType()) { diff --git a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/support/DynamoDBEntityMetadataSupport.java b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/support/DynamoDBEntityMetadataSupport.java index 896e75d6..ced857e7 100644 --- a/src/main/java/org/socialsignin/spring/data/dynamodb/repository/support/DynamoDBEntityMetadataSupport.java +++ b/src/main/java/org/socialsignin/spring/data/dynamodb/repository/support/DynamoDBEntityMetadataSupport.java @@ -50,7 +50,7 @@ public class DynamoDBEntityMetadataSupport implements DynamoDBHashKeyExtr private List globalIndexRangeKeyPropertyNames; private String dynamoDBTableName; - private Map globalSecondaryIndexNames = new HashMap(); + private Map globalSecondaryIndexNames = new HashMap<>(); @Override public String getDynamoDBTableName() { @@ -70,9 +70,9 @@ public DynamoDBEntityMetadataSupport(final Class domainType) { DynamoDBTable table = this.domainType.getAnnotation(DynamoDBTable.class); Assert.notNull(table, "Domain type must by annotated with DynamoDBTable!"); this.dynamoDBTableName = table.tableName(); - this.globalSecondaryIndexNames = new HashMap(); - this.globalIndexHashKeyPropertyNames = new ArrayList(); - this.globalIndexRangeKeyPropertyNames = new ArrayList(); + this.globalSecondaryIndexNames = new HashMap<>(); + this.globalIndexHashKeyPropertyNames = new ArrayList<>(); + this.globalIndexRangeKeyPropertyNames = new ArrayList<>(); ReflectionUtils.doWithMethods(domainType, new MethodCallback() { @Override public void doWith(Method method) { diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/repository/query/nested/Address.java b/src/test/java/org/socialsignin/spring/data/dynamodb/repository/query/nested/Address.java new file mode 100644 index 00000000..cb3bb0fe --- /dev/null +++ b/src/test/java/org/socialsignin/spring/data/dynamodb/repository/query/nested/Address.java @@ -0,0 +1,37 @@ +/** + * Copyright © 2013 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.query.nested; + +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBDocument; + +@DynamoDBDocument +public class Address { + private String city; + private String country; + + public String getCity() { + return city; + } + public void setCity(String city) { + this.city = city; + } + public String getCountry() { + return country; + } + public void setCountry(String country) { + this.country = country; + } +} \ No newline at end of file diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/repository/query/nested/NestedPropertiesTest.java b/src/test/java/org/socialsignin/spring/data/dynamodb/repository/query/nested/NestedPropertiesTest.java new file mode 100644 index 00000000..ae5cc454 --- /dev/null +++ b/src/test/java/org/socialsignin/spring/data/dynamodb/repository/query/nested/NestedPropertiesTest.java @@ -0,0 +1,59 @@ +package org.socialsignin.spring.data.dynamodb.repository.query.nested; + +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.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.junit4.SpringJUnit4ClassRunner; + +import java.util.List; + +import static org.junit.Assert.assertEquals; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = {DynamoDBLocalResource.class, NestedPropertiesTest.TestAppConfig.class}) +public class NestedPropertiesTest { + + @Configuration + @EnableDynamoDBRepositories(basePackages = "org.socialsignin.spring.data.dynamodb.query.nested") + public static class TestAppConfig { + } + + @Autowired + private PersonRepository personRepository; + + @Test + public void testNestedProperty() { + + Address usaAddress = new Address(); + usaAddress.setCity("New York"); + usaAddress.setCountry("USA"); + + Address deAddress = new Address(); + deAddress.setCity("Frankfurt"); + deAddress.setCity("Germany"); + + Person p1 = new Person(); + p1.setName("personName"); + p1.setPhone("phone"); + p1.setArea("area"); + p1.setAddress(usaAddress); + + Person p2 = new Person(); + p2.setName("otherName"); + p2.setPhone("42"); + p2.setArea("otherArea"); + p2.setAddress(deAddress); + +/// personRepository.save(p1); + + List actual = personRepository.findByAddressCountry("USA"); + assertEquals(1, actual.size()); + + actual = personRepository.findByPhone("42"); + assertEquals(1, actual.size()); + } +} diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/repository/query/nested/Person.java b/src/test/java/org/socialsignin/spring/data/dynamodb/repository/query/nested/Person.java new file mode 100644 index 00000000..3bf9e822 --- /dev/null +++ b/src/test/java/org/socialsignin/spring/data/dynamodb/repository/query/nested/Person.java @@ -0,0 +1,65 @@ +/** + * Copyright © 2013 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.query.nested; + +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBRangeKey; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable; +import org.springframework.data.annotation.Id; + +@DynamoDBTable(tableName = "Person") +public class Person { + + @Id + private PersonId personId; + + private String phone; + private Address address; + + @DynamoDBHashKey + public String getName() { + return personId != null ? personId.getName() : null; + } + + @DynamoDBRangeKey + public String getArea() { + return personId != null ? personId.getArea() : null; + } + public Address getAddress() { + return address; + } + public String getPhone() { + return phone; + } + public void setPhone(String phone) { + this.phone = phone; + } + public void setName(String name) { + if (personId == null) { + personId = new PersonId(); + } + this.personId.setName(name); + } + public void setArea(String area) { + if (personId == null) { + personId = new PersonId(); + } + this.personId.setArea(area); + } + public void setAddress(Address address) { + this.address = address; + } +} \ No newline at end of file diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/repository/query/nested/PersonId.java b/src/test/java/org/socialsignin/spring/data/dynamodb/repository/query/nested/PersonId.java new file mode 100644 index 00000000..f78b55f2 --- /dev/null +++ b/src/test/java/org/socialsignin/spring/data/dynamodb/repository/query/nested/PersonId.java @@ -0,0 +1,53 @@ +/** + * Copyright © 2013 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.query.nested; + +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBRangeKey; + +import java.io.Serializable; + +public class PersonId implements Serializable { + + private static final long serialVersionUID = 1L; + + private String name; + private String area; + + @DynamoDBRangeKey + public String getArea() { + return area; + } + + @DynamoDBHashKey + public String getName() { + return name; + } + + public PersonId() {} + + public PersonId(String name, String area) { + this.name = name; + this.area = area; + } + public void setName(String name) { + this.name = name; + } + public void setArea(String area) { + this.area = area; + } +} + diff --git a/src/test/java/org/socialsignin/spring/data/dynamodb/repository/query/nested/PersonRepository.java b/src/test/java/org/socialsignin/spring/data/dynamodb/repository/query/nested/PersonRepository.java new file mode 100644 index 00000000..092b8f32 --- /dev/null +++ b/src/test/java/org/socialsignin/spring/data/dynamodb/repository/query/nested/PersonRepository.java @@ -0,0 +1,36 @@ +/** + * Copyright © 2013 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.query.nested; + +import org.socialsignin.spring.data.dynamodb.repository.EnableScan; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +public interface PersonRepository extends PagingAndSortingRepository { + + Person findByNameAndArea(@Param("name") String name, @Param("area") String area); + + @EnableScan + List findByArea(@Param("area") String area); + + @EnableScan + List findByPhone(@Param("phone") String phone); + + @EnableScan + List findByAddressCountry(@Param("country") String country); +} \ No newline at end of file diff --git a/src/test/resources/person_table.json b/src/test/resources/person_table.json new file mode 100755 index 00000000..a6953561 --- /dev/null +++ b/src/test/resources/person_table.json @@ -0,0 +1,27 @@ +{ + "AttributeDefinitions": [ + { + "AttributeName": "Name", + "AttributeType": "S" + }, + { + "AttributeName": "Area", + "AttributeType": "S" + } + ], + "KeySchema": [ + { + "AttributeName": "Name", + "KeyType": "HASH" + }, + { + "AttributeName": "Area", + "KeyType": "RANGE" + } + ], + "ProvisionedThroughput": { + "ReadCapacityUnits": "10", + "WriteCapacityUnits": "10" + }, + "TableName": "person" +} \ No newline at end of file