Skip to content

DDB Enhanced: Expose attribute extractors and converters #1757

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

Conversation

musketyr
Copy link
Contributor

@musketyr musketyr commented Apr 1, 2020

Description

This PR exposes the Attribute and AttributeType API from the TableSchema to allow
easier generalization of the construction of queries.

Motivation and Context

In version 1, there were API to convert the Java value to the AttributeValue (DynamoDBMapperFieldModel) which is not present in version 2.

See RangeConditionCollector for an example usage with version 1. Exposing the already present information about the attributes enables reimplementing similar behaviour for version 2.

Testing

The main problem with this PR might be that AttributeType has been moved to the public API so the package has been changed. This might break some existing applications which ignored that AttributeType was a internal API so far.

Screenshots (if appropriate)

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)

NOTE: this change is making an internal interface into public one which may break some existing 3rd party code which relies on the internal API. As the interface was marked as internal before then it should be considered non-breaking change.

Checklist

  • I have read the CONTRIBUTING document
  • Local run of mvn install succeeds
  • My code follows the code style of this project
  • My change requires a change to the Javadoc documentation
  • I have updated the Javadoc documentation accordingly
  • I have read the README document
  • I have added tests to cover my changes
  • All new and existing tests passed
  • A short description of the change has been added to the CHANGELOG
  • My change is to implement 1.11 parity feature and I have updated LaunchChangelog

License

  • I confirm that this pull request can be released under the Apache 2 license

@codecov-io
Copy link

codecov-io commented Apr 1, 2020

Codecov Report

Merging #1757 into master will decrease coverage by 0.01%.
The diff coverage is 86.66%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master    #1757      +/-   ##
============================================
- Coverage     76.31%   76.30%   -0.02%     
  Complexity      182      182              
============================================
  Files          1072     1072              
  Lines         32247    32250       +3     
  Branches       2519     2519              
============================================
- Hits          24608    24607       -1     
- Misses         6400     6402       +2     
- Partials       1239     1241       +2     
Flag Coverage Δ Complexity Δ
#unittests 76.30% <86.66%> (-0.02%) 182.00 <0.00> (ø)
Impacted Files Coverage Δ Complexity Δ
...e/amazon/awssdk/enhanced/dynamodb/TableSchema.java 100.00% <ø> (ø) 0.00 <0.00> (ø)
.../dynamodb/internal/mapper/StaticAttributeType.java 100.00% <ø> (ø) 0.00 <0.00> (ø)
...ssdk/enhanced/dynamodb/mapper/BeanTableSchema.java 84.42% <0.00%> (-0.70%) 0.00 <0.00> (ø)
...ssdk/enhanced/dynamodb/mapper/StaticAttribute.java 100.00% <ø> (ø) 0.00 <0.00> (ø)
...amodb/internal/mapper/ResolvedStaticAttribute.java 88.88% <66.66%> (-2.78%) 0.00 <0.00> (ø)
...dk/enhanced/dynamodb/mapper/StaticTableSchema.java 90.35% <100.00%> (+0.17%) 0.00 <0.00> (ø)
...ssdk/core/internal/async/FileAsyncRequestBody.java 84.76% <0.00%> (-2.86%) 0.00% <0.00%> (ø%)
...o/netty/internal/nrs/HttpStreamsClientHandler.java 67.79% <0.00%> (+1.69%) 0.00% <0.00%> (ø%)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d4ea84f...f1514ee. Read the comment docs.

@bmaizels
Copy link
Contributor

bmaizels commented Apr 1, 2020

Hi @musketyr, thank you for taking a look at the enhanced client preview and also submitting your contribution to improve the experience.

Before really drilling on the change itself I first need to make sure I understand the motivation and what it is you are trying to do because generally speaking we are very resistant to making internal interfaces public unless absolutely necessary as that restricts what we can do with those interfaces in the future, so the cost is high.

Based on your description of your use-case it sounds like you are trying to apply a TableSchema to extract and convert one or more object modeled attributes to their AttributeValue equivalents that would be written to the DynamoDB table if you were doing, say, a PutItem?

If that is true, is this existing method in TableSchema not sufficient to accomplish that?

    /**
     * Takes a modelled object and extracts a specific set of attributes which are then returned as a map of
     * {@link AttributeValue} that the DynamoDb low-level SDK can work with. This method is typically used to extract
     * just the key attributes of a modelled item and will not ignore nulls on the modelled object.
     *
     * @param item The modelled Java object to extract the map of attributes from.
     * @param attributes A collection of attribute names to extract into the output map.
     * @return A map of String to {@link AttributeValue} representing the requested modelled attributes in the model
     * object.
     */
    Map<String, AttributeValue> itemToMap(T item, Collection<String> attributes);

@bmaizels
Copy link
Contributor

bmaizels commented Apr 1, 2020

Also, to convert and retrieve a single AttributeValue you can use:

    /**
     * Returns a single attribute value from the modelled object.
     *
     * @param item The modelled Java object to extract the attribute from.
     * @param key The attribute name describing which attribute to extract.
     * @return A single {@link AttributeValue} representing the requested modelled attribute in the model object or
     * null if the attribute has not been set with a value in the modelled object.
     */
    AttributeValue attributeValue(T item, String key);

@musketyr
Copy link
Contributor Author

musketyr commented Apr 1, 2020

Hi @bmaizels,

thank you for a quick answer! The motivation is to reimplement advanced queries and updates using the declarative clients in Micronaut. There is a working version using v1.

https://agorapulse.github.io/micronaut-aws-sdk/#_declarative_services_with_service

If you take a look at the @Query example

 @Query({
        query(DynamoDBEntity) {
            hash hashKey
            range { between DynamoDBEntity.DATE_INDEX, after, before }
        }
    })

I would like to convert the values after and before to the AttributeValue but the only information I have is the name of the attribute (in this case an index, but can be an attribute in general as a similar DSL exists for scanning. To use the existing method I would have to populate a new object with and assign the filter values (probably using reflection or similar way)

public <T> AttributeValue convert(TableSchema<T> schema, String attrName, Object value) {
    T instance = schema.itemType().rawClass().newInstance();
    setAttrOnInstance(instance, attrName, value);
    return schema.attrributeValue(instance, attrName);
}

With the new exposed API, it would be much easier:

public <T> AttributeValue convert(TableSchema<T> schema, String attrName, Object value) {
    return schema.attribute(attrName).attributeType(). objectToAttributeValue(value);
}

This approach is much cleaner, it uses the information already present in the metamodel, it is reflection-free and it avoids unnecessary object creation.

@bmaizels
Copy link
Contributor

bmaizels commented Apr 1, 2020

@musketyr Thanks for explaining better, I understand what you are trying to do now and why you are trying to do it. Having said that I'm still hesitant to approve making these interfaces public for the aforementioned reasons. Please give me some time to think on it and discuss with my team and see if we can come up with any other ideas about how to solve this for you.

@bmaizels
Copy link
Contributor

bmaizels commented Apr 1, 2020

Please give me some time to think on it and discuss with my team and see if we can come up with any other ideas about how to solve this for you.

My initial thoughts is this use-case might be better served by the Document API we are planning to release as part of the DDB Enhanced Client. I'll get back to you.

@musketyr
Copy link
Contributor Author

musketyr commented Apr 2, 2020

Thank you! I'm just wondering, would it be more acceptable for you to add the convert method mentioned above to the TableSchema and keeping the rest of the API changes internal?

@sonarqubecloud
Copy link

sonarqubecloud bot commented Apr 2, 2020

Kudos, SonarCloud Quality Gate passed!

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities (and Security Hotspot 0 Security Hotspots to review)
Code Smell A 1 Code Smell

89.5% 89.5% Coverage
0.0% 0.0% Duplication

@musketyr
Copy link
Contributor Author

musketyr commented Apr 3, 2020

@bmaizels see #1765 for a minimal version of this PR which only adds a single method into TableSchema class.

@github-actions
Copy link

github-actions bot commented Apr 3, 2023

This is a very old issue that is probably not getting as much attention as it deserves. We encourage you to check if this is still an issue in the latest release and if you find that this is still a problem, please feel free to provide a comment or open a new issue.

@github-actions github-actions bot added closing-soon This issue will close in 4 days unless further comments are made. closed-for-staleness and removed closing-soon This issue will close in 4 days unless further comments are made. labels Apr 3, 2023
@github-actions github-actions bot closed this Apr 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants