Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for inheritance in DynamoDbMapper #832

Closed
sowdri opened this issue Aug 31, 2016 · 32 comments
Closed

Support for inheritance in DynamoDbMapper #832

sowdri opened this issue Aug 31, 2016 · 32 comments
Labels
feature-request A feature should be added or improved.

Comments

@sowdri
Copy link

sowdri commented Aug 31, 2016

I'm using dynamodb and the java class I'm storing has the following structure:

@DynamoDBTable(tableName="Animals")
class abstract Animal {

  @DynamoDBHashKey(attributeName = "Id")
  @DynamoDBAutoGeneratedKey
  String id;

}

class Dog extends Animal {
  // ... dog props
}

class Cat extends Animal {
  // ... cat props
}

I would like to save instances of Animal class to the db and retrieve them as well. Ready to supply meta information similar to @JsonTypeInfo and the likes.

Looks like this is not supported right now.

http://stackoverflow.com/questions/39221525/dynamodbmapper-support-for-inheritance

@fpoolev
Copy link

fpoolev commented Sep 1, 2016

I was able to inherit from an abstract class using DynamoDBMapper by notating both the abstract class and the subclass with the @DynamoDBTable annotation.

@sowdri
Copy link
Author

sowdri commented Sep 6, 2016

It would work if the operations are performed on Dog/Cat (concrete instances) vs Animal (abstract instance)

Support for polymorphism would mean operating on base class (put and get 'Animal' and the type information is handled automatically)

@fpoolev
Copy link

fpoolev commented Sep 6, 2016

@sowdri Yeah, I only extended my abstract class as a means to add common attributes. I only attempted performing operations on my concrete classes. I did not attempt any polymorphism.

@kiiadi
Copy link
Contributor

kiiadi commented Sep 19, 2016

@sowdri - it's certain possible to save polymorphic types - in this case the mapper can get to the concrete implementation and uses the annotations on that to do the persistence to dynamo (ie: Cat will pick up additional properties of the Cat object and add those fields)

class Cat extends Animal {
  @DynamoDBAttribute(attributeName = "furLength")
  public String getFurLength()  { return furLength; }
  public void setFurLength()  { this.furLength = furLength; }
}

Animal cat = new Cat();
cat.setFurLength("long");
mapper.save(cat);

In this case, the furLength property will get persisted.

However at present the way the load mechanism works one must specify the concrete type you're trying to load.

I like the idea of having an additional annotation on the base-class that specifies sub-types to convert to - this would mean we'd need to store additional fields against the object in dynamo - but it could be a cool feature.

This is something we can look to add in a future release.

@kiiadi kiiadi added the feature-request A feature should be added or improved. label Sep 19, 2016
@sowdri
Copy link
Author

sowdri commented Sep 27, 2016

@kiiadi Thanks for your reply.

For anyone who is looking for a solution for this problem. You could simple use Jackson for serialization/deserialization and use the low-level Item API (using the Item.fromJson() and Item.toJson()) for putting and getting polymorphic types in and out of Dynamo.

For anyone looking for a quick solution until this feature is implemented, I've posted the code of a base class just for reference.

public abstract class DynamoServiceImpl<T extends Base<String>> implements DynamoService<T> {

    @Autowired
    @AwsConfig.DynamoMapper
    private ObjectMapper objectMapper;

    @Autowired
    private DynamoDB db;

    abstract String getTable();

    abstract Class<?> getType();

    @Override
    public T get(String id) {
        Table table = db.getTable(getTable());
        Item item = table.getItem("id", id);
        String s = item.toJSON();

        Object obj;

        try {
            obj = objectMapper.readValue(s, getType());
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

        return (T)obj;
    }

    @Override
    public T put(T obj) {
        /**
         * Check if item has id, else populate it
         */
        if (obj.getId() == null) {
            obj.setId(uuid());
        }

        Table table = db.getTable(getTable());

        String jsonStr;
        try {
            jsonStr = objectMapper.writeValueAsString(obj);
            System.out.println(jsonStr);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            throw new RuntimeException("Cannot write item");
        }

        Item item = Item.fromJSON(jsonStr);

        table.putItem(item);
        return obj;
    }
}```

@ranjitparva
Copy link

+1 Looking for the exact same feature in DynamoDBMapper.

@arnoldtempfli
Copy link

+1

2 similar comments
@matelang
Copy link

matelang commented Nov 9, 2016

+1

@destebanm
Copy link

+1

@oscartoledo
Copy link

+1

8 similar comments
@safrain
Copy link

safrain commented Mar 24, 2017

+1

@bita-c
Copy link

bita-c commented Apr 26, 2017

+1

@david-ratcliffe
Copy link

+1

@chrislockSB
Copy link

+1

@gleb-urvanov
Copy link

+1

@brunodelphim
Copy link

+1

@andrerip
Copy link

+1

@zachpepsin
Copy link

+1

@kiiadi
Copy link
Contributor

kiiadi commented Jul 12, 2017

Initial proposal for supporting polymorphism in DynamoDB mapper - pr #1229

@ghost
Copy link

ghost commented Aug 17, 2017

+1

@AliakseiMat
Copy link

Any updates about when it will be implemented? It's very useful feature.

@david-ratcliffe
Copy link

david-ratcliffe commented Aug 24, 2017

As @fpoolev had pointed out above (in Sep 2016), simply adding (dummy, unused) annotations to super-classes seems to work for cases where dynamic typing isn't required (e.g., for a dummy table named X):

@DynamoDBTable(tableName = "X")
public abstract class X ...

Table "X" needn't exist, and such dummy annotations permit attributes of classes like X to appear in documents for subclasses of X.

@ben-bourdin451
Copy link

@dratc Unfortunately as I understand it, this does not fully fix this issue as it won't allow for dynamic types and linking using the @DynamoDBDocument annotations to compose varying types. It is probably still possible to achieve similar behaviour by using the low level SDKs for dynamo but having native support in the mapper would make our lives much easier 😄

We already use the solution you mentioned above, which is limited, and would still very much like the flexibility this issue addresses!

@kiiadi
Copy link
Contributor

kiiadi commented Aug 25, 2017

@ben-bourdin451 I'm not sure I fully understand your use-case - what do you mean by dynamic types?

@AliakseiMat @dratc I've put out a PR #1229 which I'm looking to get some feedback on.

@dimPhotobox
Copy link

Hello,

moving from aws-sdk.version : 1.10.49 to 1.11.246

my previous polymorphism implementation is not working anymore... :(

(previously working with lombok
@Getter (onMethod = @__({@DynamoDBAttribute, @ApiModelProperty("...")}))
moved to simple @DynamoDBAttribute with real getters & setters do not change a thing...)

any info related to this issue ?
seems like sdk is not ascending compatible...
what a deception :(

sincerely

i42

@mdamak
Copy link

mdamak commented Feb 28, 2020

Any updates on this please?

@SergiiSopin
Copy link

This seems to be very important feature. Any progress with it?

@bercik
Copy link

bercik commented May 15, 2020

I can agree with @SergiiSopin without this you need to do some "hacky" things to persist such objects. Could you consider implementing support for this?

@millems
Copy link
Contributor

millems commented May 15, 2020

It's unlikely that this will be prioritized for V1 of the Java SDK, because of the associated performance and operational risks. We're primarily focused on V2 of the Java SDK, so we will be implementing this there at some point, but I don't have an ETA.

I'll check in with the team whether we want to close this issue to prevent confusion.

@millems
Copy link
Contributor

millems commented Jun 2, 2020

Unfortunately the attached pull request doesn't have enough tests (either functional or performance) for the Java SDK team to merge as-is, and we haven't prioritized doing that testing, since a lot of people are very vocal about wanting us to focus on V2 of the SDK.

I've created a feature request for adding this feature to the V2 DynamoDB enhanced client: aws/aws-sdk-java-v2#1870. We're currently leaning towards just doing this with the enhanced client in V2, since that's much better tested and understood.

@debora-ito
Copy link
Member

Closing this issue before going into Maintenance Mode.

Please track the request for a v2 equivalent of this feature in aws/aws-sdk-java-v2#1870.

Reference:

  • Announcing end-of-support for AWS SDK for Java v1.x effective December 31, 2025 - blog post

@debora-ito debora-ito closed this as not planned Won't fix, can't repro, duplicate, stale Jul 26, 2024
Copy link

This issue is now closed.

Comments on closed issues are hard for our team to see.
If you need more assistance, please open a new issue that references this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request A feature should be added or improved.
Projects
None yet
Development

No branches or pull requests