Code Monkey home page Code Monkey logo

spring-data-dynamodb's Introduction

codecov.io Build Status Maven Central Developer Workspace Donation badge

Spring Data DynamoDB

The primary goal of the Spring® Data project is to make it easier to build Spring-powered applications that use data access technologies.

This module deals with enhanced support for a data access layer built on AWS DynamoDB.

Technical infos can be found on the project page.

Supported Features

Demo application

For a demo of spring-data-dynamodb, using spring-data-rest to showcase DynamoDB repositories exposed with REST, please see spring-data-dynamodb-examples.

Quick Start

Download the JAR though Maven Central (SNAPSHOT builds are available via the OSSRH snapshot repository ):

<dependency>
  <groupId>com.github.derjust</groupId>
  <artifactId>spring-data-dynamodb</artifactId>
  <version>5.1.0</version>
</dependency>

Setup DynamoDB configuration as well as enabling Spring-Data DynamoDB repository support via Annotation (XML-based configuration)

Create a DynamoDB entity User for this table:

@DynamoDBTable(tableName = "User")
public class User {

	private String id;
	private String firstName;
	private String lastName;

	public User() {
		// Default constructor is required by AWS DynamoDB SDK
	}

	public User(String firstName, String lastName) {
		this.firstName = firstName;
		this.lastName = lastName;
	}

	@DynamoDBHashKey
	@DynamoDBAutoGeneratedKey
	public String getId() {
		return id;
	}

	@DynamoDBAttribute
	public String getFirstName() {
		return firstName;
	}

	@DynamoDBAttribute
	public String getLastName() {
		return lastName;
	}

	//setter & hashCode & equals
}

Create a CRUD repository interface UserRepository:

@EnableScan
public interface UserRepository extends CrudRepository<User, String> {
  List<User> findByLastName(String lastName);
  List<User> findByFirstName(String firstName);
}

or for paging and sorting...

public interface PagingUserRepository extends PagingAndSortingRepository<User, String> {
	Page<User> findByLastName(String lastName, Pageable pageable);
	Page<User> findByFirstName(String firstName, Pageable pageable);

	@EnableScan
	@EnableScanCount
	Page<User> findAll(Pageable pageable);
}

Create the configuration class DynamoDBConfig:

@Configuration
@EnableDynamoDBRepositories(basePackageClasses = UserRepository.class)
public static class DynamoDBConfig {

	@Value("${amazon.aws.accesskey}")
	private String amazonAWSAccessKey;

	@Value("${amazon.aws.secretkey}")
	private String amazonAWSSecretKey;

	public AWSCredentialsProvider amazonAWSCredentialsProvider() {
		return new AWSStaticCredentialsProvider(amazonAWSCredentials());
	}

	@Bean
	public AWSCredentials amazonAWSCredentials() {
		return new BasicAWSCredentials(amazonAWSAccessKey, amazonAWSSecretKey);
	}

	@Bean
	public DynamoDBMapperConfig dynamoDBMapperConfig() {
		return DynamoDBMapperConfig.DEFAULT;
	}

	@Bean
	public DynamoDBMapper dynamoDBMapper(AmazonDynamoDB amazonDynamoDB, DynamoDBMapperConfig config) {
		return new DynamoDBMapper(amazonDynamoDB, config);
	}

	@Bean
	public AmazonDynamoDB amazonDynamoDB() {
		return AmazonDynamoDBClientBuilder.standard().withCredentials(amazonAWSCredentialsProvider())
				.withRegion(Regions.US_EAST_1).build();
	}
}

And finally write a test client UserRepositoryIT or start calling it from your existing Spring code.

The full source code is available at spring-data-dynamodb-examples' simple example

More

More sample code can be found in the spring-data-dynamodb-examples project.

Advanced topics can be found in the wiki.

Version & Spring Framework compatibility

The major and minor number of this library refers to the compatible Spring framework version. The build number is used as specified by SEMVER.

API changes will follow SEMVER and loosly the Spring Framework releases.

spring-data-dynamodb version Spring Boot compatibility Spring Framework compatibility Spring Data compatibility
1.0.x >= 3.1 && < 4.2
4.2.x >= 1.3.0 && < 1.4.0 >= 4.2 && < 4.3 Gosling-SR1
4.3.x >= 1.4.0 && < 2.0 >= 4.3 && < 5.0 Gosling-SR1
4.4.x >= 1.4.0 && < 2.0 >= 4.3 && < 5.0 Hopper-SR2
4.5.x >= 1.4.0 && < 2.0 >= 4.3 && < 5.0 Ingalls
5.0.x >= 2.0 && < 2.1 >= 5.0 && < 5.1 Kay-SR1
5.1.x >= 2.1 >= 5.1 Lovelace-SR1
spring-data-dynamodb depends directly on spring-data as also spring-context, spring-data and spring-tx.

compile and runtime dependencies are kept to a minimum to allow easy integartion, for example into Spring-Boot projects.

History

The code base has some history already in it - let's clarify it a bit:

The Java package name/XSD namespace never changed from org.socialsignin.spring.data.dynamodb. But the XSD is now also available at https://derjust.github.io/spring-data-dynamodb/spring-dynamodb-1.0.xsd.

spring-data-dynamodb's People

Contributors

alexarana avatar blx avatar boostchicken avatar boothen avatar cmleroy avatar daquino avatar dasniko avatar davinpidoto avatar derjust avatar enriquezrene avatar gauravbrills avatar matthias-hampel avatar michaellavelle avatar mtedone avatar paulatbox avatar ryonday avatar srekapalli avatar treidel avatar vitolimandibhrata avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spring-data-dynamodb's Issues

Date marshaller UTC time zone discrepancy

I recently ran into a problem in which a DynamoDB Date field was marshalling differently depending on the time zone of the machine it was being run on. We are attempting to read a preexisting UTC epoch time from a file and marshall the Date object created from this time into a UTC timestamp on a remote server. After some experimentation, we realized that we could fix the problem by simply changing the remote server time zone to our local time zone however I would like the ability to leave the remote server set using the UTC time zone.

I did some initial investigation and I am wondering if there may be problem with the Date marshaller if the Date that is being marshalled is already measured in reference to the UTC time zone. I noticed that the SimpleDateFormat always sets the time zone to UTC.

https://docs.oracle.com/javase/8/docs/api/java/text/DateFormat.html#setTimeZone-java.util.TimeZone-

The classes in question so far are:
DateDynamoDBMarshaller.java
Date2IsoDynamoDBMarshaller.java
Date2EpocheDynamoDBMarshaller.java

Does anyone have any ideas what is going on? I would greatly appreciate any and all help.

Scan and Query operations

Regarding a lightweight implementation of a repository - for instance DynamoDBPagingAndSortingRepository and a method findByXandY() - Is there a way to choose between a actual scan and a query? And is there a default when searching for gsi's, lets say X and Y are parts of a composite gsi. And also is there a difference between Pageable and just returning a List regarding scan and query. My aim is to get a better view when a scan and query is taking place, for possible performance issues. Thanks.

DynamoDBIdIsHashAndRangeKeyEntityInformationImpl throws an exception when using both hash and range key definitions

When using both @DynamoDBHashKey and @DynamoDBRangeKey the extractor org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBIdIsHashAndRangeKeyEntityInformationImpl throws an exception because:

1 - No @Id field is declared (org.springframework.data.repository.core.support.ReflectionEntityInformation base class forces a explicit declaration of an annotated id)

2 - When @Id is used (for example in the hash key), it tries to look for fields annotated with @DynamoDBHashKey and/or @DynamoDBRangeKey within the id type (usually a String).

Using a separate type for the composite key also fails, since it class mapping still requires the hash key annotation.

Support returning Optional<?> and empty Collections instead of throwing EmptyResultDataAccessException/IncorrectResultSizeDataAccessException

The current spring-data-dynamodb throws EmptyResultDataAccessException or IncorrectResultSizeDataAccessException when queries fail. As these are unchecked exceptions, it really makes my jaw drop when it happens unexpectedly since most times these are recoverable errors for my codebase.

Recently, I've been switching my code over to using the Optional<T> monad, and Spring has touted support for this in new versions of spring-data. It is much more developer friendly to return these wrapper types for single-item queries and to return empty Collection/Iterable for empty multi-item queries.

java.lang.ClassNotFoundException: com.amazonaws.ClientConfigurationFactory

Hi,

I am trying to setup this library in my existing Spring boot project but I getting the following error.

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.amazonaws.services.dynamodbv2.AmazonDynamoDB]: Factory method 'amazonDynamoDB' threw exception; nested exception is java.lang.NoClassDefFoundError: com/amazonaws/ClientConfigurationFactory

I am using Spring Boot 1.4 and I just added the following to my pom.xml

<dependency>
            <groupId>com.github.derjust</groupId>
            <artifactId>spring-data-dynamodb</artifactId>
            <version>4.4.1</version>
        </dependency>

Should I add the AWS SDK separately to my pom.xml too?

Do you have an example project setup that I can facilitate the basic functionality of the homepage README? Messing around with alot of transitive dependancies can be abit of a minefield.

Investigate support for limits.

Perhaps this is already supported, but I am unclear which dynamically generated query features are supported.

Below are examples from:
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/

User findFirstByOrderByLastnameAsc();

User findTopByOrderByAgeDesc();

Page queryFirst10ByLastname(String lastname, Pageable pageable);

Slice findTop3ByLastname(String lastname, Pageable pageable);

List findFirst10ByLastname(String lastname, Sort sort);

List findTop10ByLastname(String lastname, Pageable pageable);

Example for 'Altering table name during runtime' seems broken

Hello guys,

Im fairly new to the whole Spring-thing, however I have great colleagues around me who are more experienced with Spring.
Now I got into a problem where I needed to prefix the Dynamo tables, so that we can make distinction between the various test environments, live, etc.
A colleague pointed me towards your wiki (Alter-table-name-during-runtime) where I found an example to get it to work. However, it seems that (atleast my Spring Tool Suite) doesn't like it.

On this pastebin you can find the code I copied and the error that STS throws is at line 20 and sounds as following:
The method setTableNameResolver(DynamoDBMapperConfig.TableNameResolver) in the type DynamoDBMapperConfig.Builder is not applicable for the arguments (DynamoDBMapperConfig.TableNameOverride)

Is there something I don't fully understand yet, which introduces this error or has something changed in related parts of the code?

Cheers and thanks in advance!

deleteBy...And... is not deleting records in Dynamo

repo.deletByKeyAndOtherKey(key, otherKey) throws EmptyResultDataAccessException when no matching records exists, but works without exception if there is one match.

In both cases no records actually deleted from database

Fails to create query condition for an index when @DynamoDBMarshaller is annotating a field and not a method.

I have the following setup:

DynamoDB Table - subscription

  • String id - Hash Key
  • String status - GSI ("status-index")
public enum Status {
    GOOD,
    BAD;
}

public class StatusMarshaller implements DynamoDBMarshaller<Status> {
    // Implementation
}

@DynamoDBTable(tableName = "subscription")
public class Subscription {

    @DynamoDBHashKey
    @DynamoDBAutoGeneratedKey
    private String id;

    @DynamoDBIndexHashKey(globalSecondaryIndexName = "status-index")
    @DynamoDBMarshalling(marshallerClass = StatusMarshaller.class)
    private Status status;
}

public interface SubscriptionRepository extends PagingAndSortingRepository<Subscription, String> {
    List<Subscription> findByStatus(Status status);
}

When I invoke the findByStatus method I see this exception occur:

Caused by: java.lang.RuntimeException: Cannot create condition for type:class com.experian.ecs.subscription.model.SubscriptionStatus property conditions must be String,Number or Boolean, or have a DynamoDBMarshaller configured
    at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQueryCriteria.addAttributeValue(AbstractDynamoDBQueryCriteria.java:606) ~[spring-data-dynamodb-4.3.1.jar:na]
    at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQueryCriteria.createSingleValueCondition(AbstractDynamoDBQueryCriteria.java:627) ~[spring-data-dynamodb-4.3.1.jar:na]
    at org.socialsignin.spring.data.dynamodb.repository.query.DynamoDBEntityWithHashKeyOnlyCriteria.withPropertyEquals(DynamoDBEntityWithHashKeyOnlyCriteria.java:119) ~[spring-data-dynamodb-4.3.1.jar:na]
    at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQueryCreator.addCriteria(AbstractDynamoDBQueryCreator.java:130) ~[spring-data-dynamodb-4.3.1.jar:na]
    at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQueryCreator.create(AbstractDynamoDBQueryCreator.java:67) ~[spring-data-dynamodb-4.3.1.jar:na]
    at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQueryCreator.create(AbstractDynamoDBQueryCreator.java:41) ~[spring-data-dynamodb-4.3.1.jar:na]
    at org.springframework.data.repository.query.parser.AbstractQueryCreator.createCriteria(AbstractQueryCreator.java:109) ~[spring-data-commons-1.11.4.RELEASE.jar:na]
    at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:88) ~[spring-data-commons-1.11.4.RELEASE.jar:na]
    at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:73) ~[spring-data-commons-1.11.4.RELEASE.jar:na]
    at org.socialsignin.spring.data.dynamodb.repository.query.PartTreeDynamoDBQuery.doCreateQuery(PartTreeDynamoDBQuery.java:65) ~[spring-data-dynamodb-4.3.1.jar:na]
    at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQuery.doCreateQueryWithPermissions(AbstractDynamoDBQuery.java:76) ~[spring-data-dynamodb-4.3.1.jar:na]
    at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQuery$CollectionExecution.execute(AbstractDynamoDBQuery.java:98) ~[spring-data-dynamodb-4.3.1.jar:na]
    at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQuery.execute(AbstractDynamoDBQuery.java:288) ~[spring-data-dynamodb-4.3.1.jar:na]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:462) ~[spring-data-commons-1.11.4.RELEASE.jar:na]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:440) ~[spring-data-commons-1.11.4.RELEASE.jar:na]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61) ~[spring-data-commons-1.11.4.RELEASE.jar:na]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at com.sun.proxy.$Proxy100.findByStatus(Unknown Source) ~[na:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_92]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_92]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_92]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_92]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) ~[spring-tx-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:97) ~[spring-aop-4.2.6.RELEASE.

When I change the subscription class to this it starts working:

@DynamoDBTable(tableName = "subscription")
public class Subscription {

    @DynamoDBHashKey
    @DynamoDBAutoGeneratedKey
    private String id;

    @DynamoDBIndexHashKey(globalSecondaryIndexName = "status-index")
    private Status status;

    @Override
    @DynamoDBMarshalling(marshallerClass = StatusMarshaller.class)
    public Status getStatus() {
        return status;
    }
}

It appears to be this method that is only inspecting methods for a marshaller and not looking at properties? https://github.com/derjust/spring-data-dynamodb/blob/master/src/main/java/org/socialsignin/spring/data/dynamodb/repository/support/DynamoDBEntityMetadataSupport.java#L288

I am using lombok to generate getters and setters so I normally place all of my annotations at the property level.

PersistentEntity must not be null

I have code that is working expect that if any data is returned from dynamodb then I get "PersistentEntity must not be null". If the table is empty then I don't get any error. I have tried a few solutions but have not figured out what the problem is.
I see that the gemfire project had the same problem last year (spring-guides/gs-accessing-gemfire-data-rest#1).
Here is the important part of my POM.

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.derjust</groupId>
            <artifactId>spring-data-dynamodb</artifactId>
            <version>${springdata.dynamodb.version}</version>
        </dependency>

DynamoDBMarshalling field annotation is ignored in DynamoDBEntityMetadataSupport

We used @DynamoDBMarshalling as a field annotation in our model class to marshal a java enum.
Saving and loading works, but when we use this field within a criteria we get an exception in AbstractDynamoDBQueryCriteria stating Cannot create condition for type:class xxx.domain.Status property conditions must be String,Number or Boolean, or have a DynamoDBMarshaller configured.

In class DynamoDBEntityMetadataSupport method public DynamoDBMarshaller<?> getMarshallerForProperty(final String propertyName) the logic only checks for an annotation on the getter, so the @DynamoDBMarshalling field annotation is ignored.

Dynamically change value of DynamoDBTable

I have three different environments (dev, stage, and prod) and for each environment I would like to change the value of the tableName in @DynamoDBTable.

In other words based on my profile the following need to be changed @DynamoDBTable(tableName="dynamic-value")

What would be the best approach to tackle this situation?

Investigate Pagination Support

Does the project support pagination without loading the whole data in memory first?

Example Request Params usage for the Pageable object:
?size=2&page=0

It seems to me that it is loading everything in memory before filtering the results because this code is invoked at some point:
https://github.com/derjust/spring-data-dynamodb/blob/master/src/main/java/org/socialsignin/spring/data/dynamodb/repository/query/AbstractDynamoDBQuery.java#L158

Is there a way to achieve this? Am I missing something?
Thanks in advance,
Francesco

how to use DynamoDBIndexHashKey and filter?

i want query index(idx_global_usrNo_feedRegDate) and filter attribute (feedOpenYn)
error message : java.lang.UnsupportedOperationException: Sort not supported for scan expressions

this my class.,.

@DynamoDBTable(tableName = "feed_user")  
public static class FeedUser {      
    @Id
    @DynamoDBHashKey
    @DynamoDBAutoGeneratedKey
    private String id;

    @DynamoDBIndexHashKey(globalSecondaryIndexName="idx_global_usrNo_feedRegDate")      
    private int usrNo;

    @DynamoDBAttribute
    private String feedId;

    @DynamoDBAttribute
    private Date feedRegDate;

    @DynamoDBAttribute
    @DynamoDBNativeBoolean
    private boolean feedOpenYn;
}


public interface FeedUserRepository extends DynamoDBPagingAndSortingRepository<Feed.FeedUser, String>{  
    public List<Feed.FeedUser> findByUsrNo(int usrNo, Pageable pageable);   
    public List<Feed.FeedUser> findByUsrNoAndFeedOpenYn(int usrNo, boolean feedOpenYn, Pageable pageable);
}

public class DynamoDBFeedTest {
    @Test
    public void feed_test(){
        PageRequest pageRequest = new PageRequest(1, 10, new Sort(Direction.DESC, "usrNo"));
        feedUserRepository.findByUsrNo(2, pageRequest); //runnable
        feedUserRepository.findByUsrNoAndFeedOpenYn(2, true, pageRequest); //not runnable 
    }
}

Investigate Order By DynamoDBIndexRangeKey Support

I would like to be able to sort the results of a global secondary index query by the global secondary index range key. Currently, the operation is not supported.

Example query signature in the paging and sorting repository.

public List<<DAO Type>> findBy<GSI HashKey>OrderBy<GSI Range>Desc

java.lang.UnsupportedOperationException: Sorting only possible by [driverId] for the criteria specified

at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQueryCriteria.applySortIfSpecified(AbstractDynamoDBQueryCriteria.java:163)
at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQueryCriteria.buildQueryRequest(AbstractDynamoDBQueryCriteria.java:114)
at org.socialsignin.spring.data.dynamodb.repository.query.DynamoDBEntityWithHashKeyOnlyCriteria.buildFinderQuery(DynamoDBEntityWithHashKeyOnlyCriteria.java:61)
at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQueryCriteria.buildQuery(AbstractDynamoDBQueryCriteria.java:433)
at org.socialsignin.spring.data.dynamodb.repository.query.DynamoDBQueryCreator.complete(DynamoDBQueryCreator.java:33)
at org.socialsignin.spring.data.dynamodb.repository.query.DynamoDBQueryCreator.complete(DynamoDBQueryCreator.java:12)
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:88)
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:73)
at org.socialsignin.spring.data.dynamodb.repository.query.PartTreeDynamoDBQuery.doCreateQuery(PartTreeDynamoDBQuery.java:65)
at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQuery.doCreateQueryWithPermissions(AbstractDynamoDBQuery.java:76)
at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQuery$CollectionExecution.execute(AbstractDynamoDBQuery.java:98)
at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQuery.execute(AbstractDynamoDBQuery.java:288)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:462)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:440)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
at com.sun.proxy.$Proxy151.findByDriverIdOrderByTimestampDesc(Unknown Source)
at <removed repository call here>org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)

no mechanism for supplying dynamically generated table names to certain types of queries

I'm using CloudFormation to make my tables, and in general stuff is working great. I'm using a TableNameResolver which covers mapping table names for most access. Unfortunately, for access that uses certain queries -- basically anything going through the QueryRequest path of DynamoDBTemplate -- I have no workable way to provide table name overrides. These code paths call DynamoDBTemplate getOverriddenTableName, but that method doesn't consider my resolver, and I don't believe mapper config table name override stuff is sufficiently powerful to work with multiple CloudFormation tables.

I've got a pull request for a fix which is small -- I added an else if case to getOverriddenTableName that considers any TableNameResolver registered with the mapper config.

Secondary Local Index query support?

I see that this supports GSI, but am having trouble (null pointer) trying to have it query using a Local Secondary Index (LSI) field I have in my DynamoDB. Is this supported, and if so is there an example?

Auditing Support

Hi @derjust,

I am working on the auditing support for spring-data-dynamodb.
https://github.com/vitolimandibhrata/spring-data-dynamodb/commits/auditing-support

Currently, it can only enable the auditing support via Java Configuration.

If you are not working on the auditing support, I can try to spend sometime to complete the code and hopefully it can be merged to your project.

Please do let me know.

Cheers,

Vito

Sample Configuration File with Auditing Support

@Configuration
@EnableDynamoDBRepositories(
        basePackages = {"com.example.repository.dynamodb"}
)
@EnableDynamoDBAuditing
public class DynamoDBConfig extends AbstractDynamoDBConfiguration {

    @Value("${aws.dynamodb.endpoint}")
    private String amazonDynamoDBEndpoint;

    @Value("${aws.accessKey}")
    private String amazonAWSAccessKey;

    @Value("${aws.secretKey}")
    private String amazonAWSSecretKey;

    @Override
    protected String getMappingBasePackage() {
        return "com.example.domain";
    }

    @Bean
    public AmazonDynamoDB amazonDynamoDB() {
        AmazonDynamoDB amazonDynamoDB = new AmazonDynamoDBClient(
                amazonAWSCredentials());
        if (StringUtils.isNotEmpty(amazonDynamoDBEndpoint)) {
            amazonDynamoDB.setEndpoint(amazonDynamoDBEndpoint);
        }
        return amazonDynamoDB;
    }

    @Bean
    public AWSCredentials amazonAWSCredentials() {
        return new BasicAWSCredentials(amazonAWSAccessKey, amazonAWSSecretKey);
    }

}

Trouble trying to query dynamo by GSI

I've read that there is support for querying by GSI but I just can't get it to work. I'd really appreciate any help to point out exactly what I'm doing wrong.

I have a dynamo table with:

  • string customerId (Hash Key)
  • string createDt (Range Key)
  • string tag
    I created a GSI called "tag" whose partition key is the string tag attribute.

I then created a method in my repository interface to query on the tag attribute:

public interface CustomerHistoryRepository extends PagingAndSortingRepository<CustomerHistory, String> {
    CustomerHistory findByTag(string tag);
}

Here is what the CustomerHistory object looks like with a composite key:

@DynamoDBTable(tableName = "customerhistory")
public class CustomerHistory implements Serializable{
    @Id
    private CustomerHistoryId id;

    @DynamoDBIndexHashKey
    private String tag;

    @DynamoDBHashKey(attributeName = "customerId")
    public String getId(){
        return id != null ? id.getCustomerId() : null;
    }

    public void setId(String customerId) {
        if(this.id == null) {
            this.id = new CustomerOfferHistoryId();
        }
        this.id.setCustomerId(customerId);
    }

    @Override
    @DynamoDBRangeKey(attributeName = "createDt")
    public String getCreateDt() {
        return id != null ? id.getCreateDt() : null;
    }

    @Override
    public void setCreateDt(String createDt) {
        if(this.id == null) {
            this.id = new CustomerOfferHistoryId();
        }

        this.id.setCreateDt(createDt);
    }
}

And here is the composite key CustomerHistoryId

@DynamoDBDocument
public class CustomerHistoryId implements Serializable{

    @DynamoDBHashKey(attributeName = "customerId")
    private String customerId;

    @DynamoDBRangeKey(attributeName = "createDt")
    private String createDt;
}

I left @EnableScan off of my repository to ensure it is not allowed to perform a scan and it throws an exception:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalArgumentException: Scanning for this query is not enabled. To enable annotate your repository method with @EnableScan, or enable scanning for all repository methods by annotating your repository interface with @EnableScan

Hopefully i'm just missing something simple! Thanks again for any help at all.

Doesn't work with Spring Data Commons 1.12.2.RELEASE

This version is used with latest Spring Boot.

Signature of QueryLookupStrategy.resolveQuery has changed from
RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, NamedQueries namedQueries);
to
RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory, NamedQueries namedQueries);

This causes a java.lang.AbstractMethodError on startup.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.