question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Spring Boot - MySQL and DynamoDB together

See original GitHub issue

Expected Behavior

Normal startup. MySQL repos work with MySQL entities (and they actually do), DynamoDB repos work with DynamoDB entities.

Actual Behavior

Spring Boot app does not start due to an error with @DynamoDBTable entity. It seems autoconfiguration does not work for DynamoDB. Should I renounce to automatic JPA configuration, maybe?

Steps to Reproduce the Problem

  1. Use “spring-boot-starter-data-jpa” within dependecies
  2. Create some repos for MySQL entities
  3. Create a DynamoDBTable entity (in the same “model” folder of MySQL entities (see ‘A’)
  4. Create DynamoDBConfig class (see ‘B’)
  5. Create DynamoDB Crude Repository (see ‘C’)
  6. Start the app

A:

package com.somotic.scm.model;

import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBRangeKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;

import javax.persistence.Id;
import java.io.Serializable;
import java.util.Date;

@DynamoDBTable(tableName = "DeviceValue")
public class DeviceValue implements Serializable {
    @Id
    private DeviceValueKey key;

    @DynamoDBAttribute(attributeName = "Value")
    private double value;

    @DynamoDBAttribute(attributeName = "LastChange")
    private Date lastChange;



    private DeviceValue(DeviceValueKey key, double value, Date lastChange) {
        this.key = key;
        this.value = value;
        this.lastChange = lastChange;
    }

    public DeviceValue(Long contextID, String tag, double value, Date lastChange) {
        this(new DeviceValueKey(contextID, tag), value, lastChange);
    }

    public DeviceValue() {}


    @DynamoDBHashKey(attributeName = "ContextID")
    public Long getContextID() {
        return (key != null) ? key.getContextID() : null;
    }

    public void setContextID(Long contextID) {
        if (key == null) {
            key = new DeviceValueKey();
        }
        key.setContextID(contextID);
    }

    @DynamoDBRangeKey(attributeName = "TAG")
    public String getTag() {
        return (key != null) ? key.getTag() : null;
    }

    public void setTag(String tag) {
        if (key == null) {
            key = new DeviceValueKey();
        }
        key.setTag(tag);
    }

    public double getValue() {
        return value;
    }

    public void setValue(double value) {
        this.value = value;
    }

    public Date getLastChange() {
        return lastChange;
    }

    public void setLastChange(Date lastChange) {
        this.lastChange = lastChange;
    }
}

B:

package com.somotic.scm.controller;

import com.amazonaws.auth.*;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableDynamoDBRepositories(value = "com.somotic.scm.repo.nosql")
public 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 AmazonDynamoDB amazonDynamoDB() {
        return AmazonDynamoDBClientBuilder.standard()
                .withCredentials(amazonAWSCredentialsProvider())
                .withRegion(Regions.EU_CENTRAL_1)
                .build();
    }
}

C:

package com.somotic.scm.repo.nosql;

import com.somotic.scm.model.DeviceValue;
import com.somotic.scm.model.DeviceValueKey;
import org.socialsignin.spring.data.dynamodb.repository.EnableScan;
import org.springframework.data.repository.CrudRepository;

@EnableScan
public interface DeviceValueRepository extends CrudRepository<DeviceValue, DeviceValueKey> {

}

Specifications

  • Spring Data DynamoDB Version: RELEASE
  • Spring Data Version: RELEASE
  • AWS SDK Version: RELEASE
  • Java Version: 1.8
  • Platform Details: Ubuntu Mate

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:8 (5 by maintainers)

github_iconTop GitHub Comments

4reactions
derjustcommented, Jan 31, 2018

Ok here we go - both repository factories try to register all repository interfaces with them -which doesn’t work very well. Especially because spring-boot does a lot of auto-magic behind the curtain via the implicit existing @EnableJpaRepositories.

The solution is to tell JPA and DynamoDB which repositories they are responsibility for (which then also drives which entities are registered):

For Spring-Boot:

@SpringBootApplication
@EnableJpaRepositories(
		includeFilters = {
		@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {
				CustomerRepository.class}
		)}
)
@EnableDynamoDBRepositories(
		includeFilters = {
				@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {
						DeviceValueRepository.class}
				)
		})
public class Application {

Same for a configuration class:

@Configuration
@EnableJpaRepositories(includeFilters = {
//or use basePackages or excludeFilters
	@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {CustomerRepository.class})
})
@EnableDynamoDBRepositories(includeFilters = {
//or use basePackages or excludeFilters
	@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {DeviceValueRepository.class})
})
public class AppConfig {

See also

2reactions
BigDrakarcommented, Feb 2, 2018

Thanks @derjust! You’ve just made my day! However, I’ve just upgraded the spring-boot-starter-parent version to 2.0.0.RC1 (enabling spring-milestone repository) and everything has settled.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Spring Data/JPA Repositories with DynamoDB and MySQL ...
The work pattern is as follows: [data POJO in, from some endpoint] -> Persist POJO into DynamoDB, retrieving the UUID of that object...
Read more >
Quick Guide to Integrate DynamoDB in Spring Boot - Baeldung
In this article, we'll explore the basics of integrating DynamoDB into a Spring Boot Application with a hands-on, practical example project.
Read more >
DynamoDB and Spring Data. Mapping entities with ... - Medium
How to integrate DynamoDB and Spring Data to map entities with hash and range keys, search with filters and paging, use global secondary ......
Read more >
How to integrate DynamoDB Into A Spring Boot Application
And we're done – we can now connect to DynamoDB from a Spring Boot Application. ... commercial-grade databases with full MySQL and PostgreSQL...
Read more >
Connect Spring Boot Application with AWS Dynamo DB
There is one difference with Dynamo DB compared to other SQL or NoSQL databases. We can interact with Dynamo DB through REST calls....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found