Giter VIP home page Giter VIP logo

spring-data-dynamodb's Introduction

codecov.io Build Status Maven Central

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 dependabot[bot] 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

spring-data-dynamodb's Issues

deleteAll() throws DynamoDBMappingException

Using 1.0.1.SNAPSHOT version of spring-data-dynamodb. It appears that calling deleteAll() on a repository goes down an unintentional codepath. DynamoDBTemplate.batchDelete() is passed a PaginatedScanList object by SimpleDynamoDBCrudRepository.deleteAll().

Here is the exception raised: com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException: Class class com.amazonaws.services.dynamodbv2.datamodeling.PaginatedScanList must be annotated with interface

Instead of invoking DynamoDBMapper.batchDelete(List) the wrong version of this function (DynamoDBMapper.batchDelete(Object...) ) is invoked. The result is later on DynamoDBReflector.getTable() is passed the PaginatedScanList class instead of the domain object class. The result is the exception which should not be seen here.

DynamoDBReflector.getTable(Class) line: 190
DynamoDBMapper.getTableName(Class, DynamoDBMapperConfig, DynamoDBReflector) line: 551 DynamoDBMapper.getTableName(Class, DynamoDBMapperConfig) line: 544
DynamoDBMapper.batchWrite(List, List, DynamoDBMapperConfig) line: 1516
DynamoDBMapper.batchDelete(Object...) line: 1393
DynamoDBTemplate.batchDelete(Iterable<?>) line: 164
DeviceRepositoryImpl(SimpleDynamoDBCrudRepository<T,ID>).deleteAll() line: 218

I'll submit a pull request with a fix in a little while.

IllegalArgumentException thrown when CRUD find has 0 result

When using CRUD operation:

@Override
public <T> T load(Class<T> domainClass, Object hashKey) {
    T entity =  dynamoDBMapper.load(domainClass, hashKey);
    maybeEmitEvent(new AfterLoadEvent<Object>(entity));
    return entity;
}

It is possible that Amazon API will return null Entity if no entity found. However the instantation of AfterLoadEvent specifically checks for null argument and throws exception if argument found. Perhaps an artifact of newer spring 4.x versions?

/**
* Constructs a prototypical Event.
*
* @param source The object on which the Event initially occurred.
* @exception IllegalArgumentException if source is null.
*/
public EventObject(Object source) {
if (source == null)
throw new IllegalArgumentException("null source");

    this.source = source;
}

Repository save() method creates a new entity instead of updating existing entity

Here's my Forum data model - note that it's slightly different from the Forum in your demo.

@DynamoDBTable(tableName = "Forums")
public class ForumData {

    @Id
    private ForumId forumId;
    private String author;
    private DateTime creationDate;


    @DynamoDBHashKey(attributeName = "Id")
    @DynamoDBAutoGeneratedKey
    public String getId() { return null == forumId ? null : forumId.getId(); }
    public void setId(String id) {
        if (null == forumId) {
            forumId = new ForumId();
        }
        forumId.setId(id);
    }

    @DynamoDBRangeKey(attributeName = "DisplayName")
    public String getDisplayName() { return null == forumId ? null : forumId.getDisplayName(); }
    public void setDisplayName(String displayName) {
        if (null == forumId) {
            forumId = new ForumId();
        }
        forumId.setDisplayName(displayName);
    }

    @DynamoDBIndexRangeKey(attributeName = "Author", localSecondaryIndexName = "AuthorIndex")
    public String getAuthor() { return author; }
    public void setAuthor(String author) { this.author = author; }

    @DynamoDBMarshalling(marshallerClass = DateTimeMarshaller.class)
    @DynamoDBAttribute(attributeName = "CreationDate")
    @JsonDeserialize(using = DateTimeDeserializer.class)
    @JsonSerialize(using = DateTimeSerializer.class)
    public DateTime getCreationDate() { return creationDate; }
    public void setCreationDate(DateTime creationDate) { this.creationDate = creationDate; }
}

And my ForumId, which will not shock you:

public class ForumId implements Serializable {

    private static final long serialVersionUID = 1L;

    private String id;
    private String displayName;


    @DynamoDBHashKey
    @DynamoDBAutoGeneratedKey
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }

    @DynamoDBRangeKey
    public String getDisplayName() { return displayName; }
    public void setDisplayName(String displayName) { this.displayName = displayName; }
}

In my REST controller, I have defined a method that maps to the PUT verb for updating my Forum resource. Note that I'm loading the forumToUpdate from the repository, changing its values, and saving it back to the repository.

@RestController
@RequestMapping("/forums")
public class ForumController {
    @PreAuthorize("hasRole('ROLE_USER')")
    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void updateForum(
            @AuthenticationPrincipal User requestor,
            @PathVariable("id") String id,
            @RequestBody Forum updatedForum)
            throws ResourceNotFoundException, AccessDeniedException {

        String username = requestor.getUsername();

        LOG.debug(String.format("Request to update forum '%s' received from '%s'", id, username));

        ForumData forumToUpdate = this.getById(id);

        // only let the author of a forum update a forum
        if (false == forumToUpdate.getAuthor().equals(username)) {
            throw new AccessDeniedException("You are not authorized to update that forum.");
        }

        // only change those values that are not null or empty
        if (StringUtils.isNotEmpty(updatedForum.getDisplayName())) {
            forumToUpdate.setDisplayName(updatedForum.getDisplayName());
        }
        if (null != updatedForum.getCreationDate()) {
            forumToUpdate.setCreationDate(updatedForum.getCreationDate());
        }

        if (StringUtils.isNotEmpty(updatedForum.getAuthor())) {
            forumToUpdate.setAuthor(updatedForum.getAuthor());
        }

        this.forumRepository.save(forumToUpdate);
    }

    private ForumData getById(String id) throws ResourceNotFoundException {
        List<ForumData> foundForums = this.forumRepository.findById(id);

        if (0 == foundForums.size()) {
            throw new ResourceNotFoundException("There is no forum with Id: " + id);
        }
        else if (foundForums.size() > 1) {
            LOG.warn(String.format("While searching for forum with id '%s', found more than one!", id));
        }

        // there should only ever be one, so just pull the first
        return foundForums.get(0);
    }
}

But now, when I get all of the Forums in the repo, there are two! (I changed creationDate, which is neither a Hash or Range Key, although it IS the range key in a local secondary index)...

[
    {
        "forumId": "9bb48bd9-05a9-41b2-8332-f871310cff10",
        "displayName": "First Forum",
        "author": "john",
        "creationDate": "2015-03-02T21:31:38.545Z"
    },
    {
        "forumId": "9bb48bd9-05a9-41b2-8332-f871310cff10",
        "displayName": "First Forum",
        "author": "john",
        "creationDate": "2015-02-16T21:31:38.545Z"
    }
]

Is this due to the fact that I'm updating the RANGE key of a local secondary index?

If this is intended behavior, does that mean that I need to delete the old entity before I save() the updated one?

And if this is not the intended behavior, have I hit a bug? Or do I simply not understand something?

Thanks!

DateTimeFormat not supporting

In repository,
public interface TestRepository extends PagingAndSortingRepository<Test, String>{
public Page findByNameAndDate(@param("name") String name,
@param("date") @DateTimeFormat(iso = ISO.DATE) Date date, Pageable pageable);
}

Here Date not getting converted to, whenever I pass its showing null cannot be accepted and also I tried formatting with @DateTimeFormat(iso = ISO.DATE, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"). But not working.
My stackoverfow link --> http://stackoverflow.com/questions/24096924/how-to-format-param-string-in-spring-data-rest

EclipseLink and Spring-data-dynamodb

Hello,

Is there a problem if I use spring-data with EclipseLink (PostgreSQL) mixed with dynamodb with this solution?

I ask cause I configure everything, but my model class is returning:
No [ManagedType] was found for the key class [com.xphub.core.model.Search] in the Metamodel - please verify that the [Managed] class was referenced in persistence.xml using a specific com.xphub.core.model.Search property or a global false element.

Anyone knows anything about that?

Maven Depedency

Dear Michael,
I need to use latest version of aws-java-sdk and you have used 1.6.9 in pom.xml. If I use latest version of sdk, its showing error in my project, Is there any way to use latest version in my project?

NullPointerException while querying on global secondary index with hash and range key both

I have a table with hash key (no range key), and a global secondary index with both hash and range key. While querying by findByIndexKeyAndRangeKey method I am getting a null pointer exception. findAll works fine for same table.

Error Logs :

java.lang.NullPointerException
    at org.socialsignin.spring.data.dynamodb.core.DynamoDBTemplate.getOverriddenTableName(DynamoDBTemplate.java:198)
    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:431)
    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:63)
    at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQuery.doCreateQueryWithPermissions(AbstractDynamoDBQuery.java:68)
    at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQuery$CollectionExecution.execute(AbstractDynamoDBQuery.java:87)
    at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQuery.execute(AbstractDynamoDBQuery.java:234)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:384)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:344)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy43.findByEnterpriseKeyAndContentVersion(Unknown Source)

Snippet of the Entity :

    @DynamoDBHashKey(attributeName = "ID")
    public String getId() {
        return id;
    }
    @DynamoDBIndexHashKey(attributeName = "EnterpriseKey", globalSecondaryIndexName="EnterpriseKey-ContentVersion-index")
    public String getEnterpriseKey() {
        return enterpriseKey;
    }
    @DynamoDBIndexRangeKey(attributeName = "ContentVersion", globalSecondaryIndexName="EnterpriseKey-ContentVersion-index")
    public String getContentVersion() {
        return contentVersion;
    }
    @DynamoDBAttribute(attributeName = "GoURL")
    public String getGoUrl() {
        return goUrl;
    }

Please let me know if I am missing something.
Thanks

http://repo.opensourceagility.com down?

This isn't a code issue but I'm not sure of an other way to contact the author. I ran across your github page and decided to try the demo. It appears repo.opensourceagility.com is having some kind of technical issue. I can ping the server however any HTTP requests seem to hang forever.

Just thought I'd let you know in case this error wasn't known.

Batch operations(insert) facility

Hi, I need to batch insert my contents into dynamodb and is there support for it to achieve that. That is I will be sending variable sized list from request and I have to enter its instance one by one into table.

For example, we have to save for a rate plan data,
sample data,
1-2 days: 30$
2-4 days: 30$
4-6 days: 50$
6-10 days: 50$

sometimes the data can be lesser and more, so I decided to save this in separate table as separate entry for each instance of data and link with hash key attribute. In dynamoDB, Batch operations are allowed and is it possible in our project to achieve that. I have searched for samples and I dint get, please help me solve this problem.

I have been using spring-data-dynamodb to create connect my API with dynamodb, its really easy to use and thanks for this awesome work.
Thank you.

Possible to upgrade validation-api to 1.1.0 for support with spring-boot

Started a new project with spring-boot and spring-boot-starter-web and added the spring-data-dynamodb dependency. Starter Web includes the hibernate validator but unfortunately that version only supports 1.1.0 of the validation-api. Had to manually exclude the validation-api dependency of this project to get things to work properly.

data validation

How to add validation to the bean fields before CRUD performs?

BUG: CountByHashAndRangeKeyQuery and CountByHashKeyQuery

DynamoDBMapper don't support: dynamoDBMapper.load(Long.class, hashKey,rangeKey) or dynamoDBMapper.load(Long.class, hashKey)
If we call CountByHashKeyQuery.getSingleResult() or CountByHashAndRangeKeyQuery.getSingleResult(), we will meet error.

DynamoDBQueryMethod.isSliceQuery method not found

java.lang.NoSuchMethodError: org.socialsignin.spring.data.dynamodb.repository.query.DynamoDBQueryMethod.isSliceQuery()Z
    at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQuery.getExecution(AbstractDynamoDBQuery.java:52)
    at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQuery.execute(AbstractDynamoDBQuery.java:234)

Can you please publish a release version

First, thanks for the project - very handy.

I understand this is still a work in progress but is there any chance you could publish a RELEASE version, even if it's just to your own repository? That way we can have a static RELEASE version dependency on what's done so far.

Updating item in Database, all fields required?

How to update only required fields from a Domain Class, for instance we have a Domain Class name variables,
String id,
String name,
String desc
and If I want update only the variable "name" for the provided "id", If I dint give "desc" variable its updated as null in the database. Is it possible to persist data which are already in Database by not updating it on.

Now I have GET the details using id and loaded into DAO and resets the name field with provided change and PUT the request to DB.

Thanks in advance.

Hash key attribute cannot be used as range key of secondary index

I realize this is probably an edge use case, but I am faced with such a use case :)

The problem arises because the dual use attribute is added twice to the allowedSortProperties List in the AbstractDynamoDBQueryCriteria.buildQueryRequestMethod.

The issue is resolved by changing line 112 of AbstractDynamoDBQueryCriteria from

applySortIfSpecified(queryRequest, allowedSortProperties);

to

applySortIfSpecified(queryRequest, new ArrayList<String>(new HashSet<String>(allowedSortProperties)));

How to use DynamoDBIndexHashKey and DynamoDBIndexRangeKey

I have created a GSI hash and key index in DynamoDB in the name "description-name-index" and I like to sort its data using range key by findBy of hash key. Here is my test code,
Domain Class
@DynamoDBTable(tableName = "test")
public class Test implements Serializable{

private static final long serialVersionUID = 1L;

private String id;
private String description;
private String name;

@DynamoDBIndexHashKey(attributeName="description")
public String getDescription() {
    return tesId;
}

public void setDescription(String description) {
    this.setDescription(description);;
}

@DynamoDBIndexRangeKey(attributeName="name")
public String getName() {
    return name;
}

public void setName(String name) {
    this.setName(name);
}

@DynamoDBHashKey(attributeName="id")
public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}

    }

and tries to fetch and sort data using findByDescriptionOrderByNameDesc(@param("decription") String description, Pageable pageable) and also I tried using @id and placed index hash and range key in a class but all in vain. Am getting 500 Internal Error but not throwing any message too. Is there any way to use GSI hash and range pair and sort them. Thank you.

Dates formatted by DefaultDynamoDBDateMarshaller are local time with 'Z' suffix

Dates are marshalled and stored correctly in DynamoDB (local times converted to UTC with Z suffix), however, dates that are provided as parameters for queries are converted to local time strings with Z suffix. Consequently, methods like findByUserIdAndTImestampBetween("joe", startDate, endDate) don't work as expected.

Changing the class

public class DefaultDynamoDBDateMarshaller extends AbstractDynamoDBDateMarshaller {

    public DefaultDynamoDBDateMarshaller() {
        super(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"));
    }
}

to the following resolves the issue

public class DefaultDynamoDBDateMarshaller extends AbstractDynamoDBDateMarshaller {

public DefaultDynamoDBDateMarshaller() {
    super(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") {
        private static final long serialVersionUID = 1L;
        {
            setTimeZone(TimeZone.getTimeZone("GMT"));
        }

    });
}
}

The DefaultDynamoDBDateMarshaller is used by AbstractDynamoDBQueryCriteria.addAttributeValue

else if (ClassUtils.isAssignable(Date.class, propertyType)) {
        List<Date> attributeValueAsList = getAttributeValueAsList(attributeValue);
        if (expandCollectionValues && attributeValueAsList != null) {
            List<String> attributeValueAsStringList = getDateListAsStringList(attributeValueAsList);
            attributeValueObject.withNS(attributeValueAsStringList);
        } else {
            Date date = (Date) attributeValue;
            String marshalledDate = new DefaultDynamoDBDateMarshaller().marshall(date);
            attributeValueObject.withS(marshalledDate);
        }
    } 

How to get the ID of an entity

I have autogenerated my hash key using @id and in JPA, there is an option like @GeneratedValue(strategy = GenerationType.IDENTITY), is there anything alternative to it where I can query ID too for the entity returned via GET. For example,

@DynamoDBTable(tableName = "test")
public class Test implements Serializable{
@id
private String id;

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

public String setId() {
    this.id = id;
}

}

I need to get this ID when GET method called. But Query not fetching ID from finder method. Is it possible @michaellavelle .. Thank you.

Support Optional for repository methods

I'd like to use the Spring Data Support for JDK 8's Optional for repository methods.

Unfortunately, right now this seems not to be supported. Instead there will be an EmptyResultDataAccessException thrown, if your custom-query result is empty...

org.springframework.dao.EmptyResultDataAccessException: No results found
    at org.socialsignin.spring.data.dynamodb.query.AbstractMultipleEntityQuery.getSingleResult(AbstractMultipleEntityQuery.java:41) ~[spring-data-dynamodb-1.0.1.jar:na]
    at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQuery$SingleEntityExecution.execute(AbstractDynamoDBQuery.java:219) ~[spring-data-dynamodb-1.0.1.jar:na]
    at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQuery.execute(AbstractDynamoDBQuery.java:234) ~[spring-data-dynamodb-1.0.1.jar:na]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:384) ~[spring-data-commons-1.8.1.RELEASE.jar:na]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:344) ~[spring-data-commons-1.8.1.RELEASE.jar:na]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.0.8.RELEASE.jar:4.0.8.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) ~[spring-aop-4.0.8.RELEASE.jar:4.0.8.RELEASE]
    at com.sun.proxy.$Proxy79.findByArticleNumber(Unknown Source) ~[na:na]

How to post to a URL with hash + range key

Domain Class:

    @DynamoDBTable(tableName = "test")
    public class Test implements Serializable{

private static final long serialVersionUID = 1L;

@Id private TestId testId;
private String description;
private String testing;

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

public void setId(String id) {
    if(testId == null){
        testId = new TestId();
    }
    this.setId(id);
}

@DynamoDBRangeKey(attributeName="name")
public String getName() {
    return testId != null ? testId.getName() : null;
}

public void setName(String name) {
    if(testId == null){
        testId = new TestId();
    }
    this.setName(name);
}

@DynamoDBAttribute(attributeName="description")
public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}

@DynamoDBAttribute(attributeName="testing")
public String getTesting() {
    return testing;
}

public void setTesting(String testing) {
    this.testing = testing;
}

public TestId getTestId() {
    return testId;
}

public void setTestId(TestId testId) {
    this.testId = testId;
}
    }

Supporter Class:

    public class TestId implements Serializable{

private String id;
private String name;

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

public void setId(String id) {
    this.id = id;
}

@DynamoDBRangeKey
public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}
    }

I think I have created Domain class correctly but What is the correct procedure to Post data into it. I have tried,
URL:
http://localhost:8080/tests
Request Body:
{"testId": {"id": "gowtham", "name": "z"}, "description": "Awesome Guy", "testing": "x"}
and
{"id": "gowtham", "name": "z", "description": "Awesome Guy", "testing": "x"}

But both failed and throws an exception as,
{
cause: {
cause: {
cause: null
message: null
}-
message: "N/A (through reference chain: pkg.Test["id"])"
}-
message: "Could not read JSON: N/A (through reference chain: pkg.Test["id"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: N/A (through reference chain: pkg["id"])"
}

But id object is present. What is the correct way to pass argument in POST method?

Unable to query by attribute when attribute is used as hashkey of more than one global secondary index

I had a table with a global secondary index with hash key 'type' and range key 'timestamp' and was able to perform queries like this:

List<Resource> resources = findByType(type);

I then added another global secondary index with the same hash key and a range key 'name'. Consequently my queries fail with RuntimeException("Don't know which index name to use");

The associated code in AbstractDynamoDBQueryCriteria.getGlobalSecondaryIndexName is:

if (getAttributeName(indexNamesEntry.getKey()).equals(singleAttributeConditions.getKey())) {
    String[] indexNames = indexNamesEntry.getValue();
    if (indexNames.length > 1) {
        throw new RuntimeException("Don't know which index name to use");
    }
    String newIndexName = indexNames[0];

    ....

Would it be acceptable to simply select the first index in this case? I realize that the order of results depend on the selected index, but in this case I'm not interested in order. When order is important, then I'll use a query such as findByTypeAndTimestamp.

Attributes names in DynamoDBRepositoryConfigExtension not compliant with schema definition

In scema (spring-dynamodb-1.0.xsd) the following attributes are supported:
amazon-dynamodb-ref
dynamodb-mapper-config-ref
dynamodb-operations-ref

while in DynamoDBRepositoryConfigExtension atributes used for getting bean in postProcess(.., XMLRepositoryConsigurationSource) method are:
amazon-dynamodb-ref (AMAZON_DYNAMODB_REF)
dynamoDBMapperConfig (DYNAMO_DB_MAPPER_CONFIG_REF)
dynamoDBOperations (DYNAMO_DB_OPERATIONS_REF)

Because of this it is impossible to define own mapperConfig or operations in xml.

Compatibility with spring-data-rest

Hi!
Thanks for this project!

I tried to integrate it with spring-data-rest to expose my entities. It worked quite well with minor adoptions:

  • Major bummer is that org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration.persistentEntities() searches for MappingContexts whereas the DynamoDBMappingContext is created with new in org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBRepositoryFactoryBean<T, S, ID>
  • Second problem is that org.socialsignin.spring.data.dynamodb.mapping.DynamoDBMappingContext.hasPersistentEntityFor(Class<?>) always returns false before a class is manually added.

To workaround those two problems, I added to my own ConfigurationBean the following code:

    @Bean
    public DynamoDBMappingContext getMappingContext() {
        DynamoDBMappingContext context = new DynamoDBMappingContext();

        context.getPersistentEntity(MyDynamoDBTable.class);

        return context;
    }

I can't really judge if that is cleaver because that leads to multiple DynamoDBContexts floating around but as they are usually only delegating to another constructor that seems fine to me.

Is there a better way to do it?
Can this somehow be incorporated into the library itself so that it is out-of-the-box Spring-Boot compatible?

Used versions:

  • Spring Boot 1.2.3.RELEASE
  • spring-data-dynamodb 1.0.1.RELEASE
  • spring-boot-starter-data-rest 1.2.3.RELEASE

Some troubles with sorting...

Hi!

I am quite new to DynamoDB and Spring-Data so maybe my question is not very bright, but I already put almost 2 days in a problem that I cannot solve - although it seems to be very easy.

I just want to list products in the descending order of creationdate - the task is as simple as that.
I tested around with the spring-data-dynamodb (I used the "Reply" as a pattern of what I want to do) and ended up having no errors when requesting DynamoDB, but I also did not get any data :(

Here is some code I ended up with:
The Repository "ProductRepository"

public interface ProductRepository extends DynamoDBPagingAndSortingRepository<ProductItem, ProductId> {

    Page<ProductItem> findByCategoryAndCreationdateAfterOrderByCreationdateDesc(ProductId product,Date creationdate,Pageable pageable);

    @EnableScan
    @EnableScanCount
    Page<ProductItem> findByProductIdOrderByCreationdateDesc(ProductId id,Pageable pageable);      
}

Here are my annotated classes:

The Item of the table "products" - ProductItem

import java.util.ArrayList;
import java.util.List;

import org.springframework.data.annotation.Id;

import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBIgnore;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBIndexHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBIndexRangeKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMarshalling;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMarshaller;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBRangeKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;

@DynamoDBTable(tableName = "products")
public class ProductItem extends Link {

    @Id
    private ProductId productId;

    private String owner;

    private String headline;
    private String description;

    private String subcategory;

    <further attributes>

    @DynamoDBHashKey(attributeName = "productId")
    @DynamoDBMarshalling(marshallerClass=ProductIdMarshaller.class)
    public ProductId getProductId() {
    return productId;
    }

    public String getCategory() {
    return productId != null ? productId.getCategory() : null;
    }

    @DynamoDBMarshalling(marshallerClass=ProductIdMarshaller.class)
    public void setProductId(ProductId id) {
    this.productId = id;
    }

    @DynamoDBRangeKey
    public String getCreationdate() {
    return productId != null ? productId.getCreationdate() : null;
    }

    public void setCreationdate(String creationdate) {
    if (productId == null) {
        productId = new ProductId();
    }
    productId.setCreationdate(creationdate);
    }
}

And the coposite ProductId which I am not sure wether I really need it:

import java.io.Serializable;
import java.util.Date;

import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAutoGeneratedKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBRangeKey;

public class ProductId implements Serializable {

    @DynamoDBHashKey
    @DynamoDBAutoGeneratedKey
    private String category;

    @DynamoDBRangeKey
    private String creationdate;

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public String getCreationdate() {
        return creationdate;
    }

    public void setCreationdate(String creationdate) {
        this.creationdate = creationdate;
    }
}

Said in SQL the only thing I need for now is something like SELECT * FROM articles ORDER BY creationdate DESC/ASC. Later I plan to add GSIs to perform other searches like "Attribute 'headline' starts with "Foo", but that is maybe another problem.

So, basically my questions is how is the setup for the table, the repository and the annotated class to have this working using spring-data-dynamodb? Am I trapped in the world of relational databases my brain cannot escape maybe?

Thank you very much in advance for your help - I am quite desperate :)

Support for @DynamoDB annotations on class fields instead of getter / setter methods

The javadoc for the @DynamoDBHashKey and other annotations state that they can be applied to the class fields. I noticed when trying to do this the instantiation of the CrudRespository fails with an error:

"Unable to find hash key getter method on class com.test.Event!"

Diving into it I saw that the DynamoDBEntityMetadataSupport class constructor scans only the methods on the doWith(Method method) of the model class.The odd thing is that once it finds the method it then looks for the field name but removing the "get" or "is" from the method. Could scan the fields first and only scan the methods if there is no annotation on the field.

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.