Skip to content

DATACOUCH-625 - Save doesn't return updated entity if immutable. #274

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

Merged

Conversation

mikereiche
Copy link
Collaborator

Modified applyUpdatedCas() to return accessor.getBean() which will
occur if the version property is Immutable.
Created applyUpdateId() that is analogous to applyUpdatedCas()
Factored out the equals() method that was used by a number of
test entity objects.

  • You have read the Spring Data contribution guidelines.
  • There is a ticket in the bug tracker for the project in our JIRA.
  • You use the code formatters provided here and have them applied to your changes. Don’t submit any formatting related changes.
  • You submit test cases (unit or integration tests) that back your changes.
  • You added yourself as author in the headers of the classes you touched. Amend the date range in the Apache license header if needed. For new types, add the license header (copy from another file and set the current year only).

@mikereiche mikereiche requested a review from daschl October 15, 2020 01:16
@@ -541,6 +541,7 @@ public void doWithPersistentProperty(final CouchbasePersistentProperty prop) {
generatedValueInfo = idProperty.findAnnotation(GeneratedValue.class);
String generatedId = generateId(generatedValueInfo, prefixes, suffixes, idAttributes);
target.setId(generatedId);
// this is not effective if id is Immutable, and accessor.setProperty() returns a new object in getBean()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Id population should happen on the Template API level, see MongoDB for reference. Note, newer versions have the Id population extracted because it happened in multiple places.

Copy link
Collaborator Author

@mikereiche mikereiche Oct 15, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After adding the update via CouchbaseTemplateSupport.applyUpdatedId() ( called by Reactive[Insert/Upsert]ByIdSupport.one(entity) which is called from the template), I left the update to the sourceObject here for two reasons - the first being that a number of unit tests depend on it (those can be fixed), the second is that if it is removed from here, it would appear to be a regression for anyone calling repository.save( sourceObject ), and expecting sourceObject to contain the id. They should be calling as savedObject = repository.save( sourceObject ). I could remove this now in hope that will result in fewer customers using it incorrectly, or wait to do it in the 4.1 release because it could be a breaking change for some.

My first idea was to have the Couchbase implementation of EntityWriter.write(source, target) return the updated object - but the signature returns void. (updating here and returning accessor.getBean() would have worked for that).

There could be one benefit from updating the source object with the id. For async/reactive calls - the generated id would be available immediately from the source object. The id from the saved object is not available until the save operation completes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's schedule any removal for the next version. We're in the RC phase with the GA release coming up Oct 28.

In any case in an async/reactive API usage scenario, it's hard to reason about when the model is being updated. In-place updates could have nasty side effects therefore we generally recommend using immutable types if you want to work with the saved/updated object instance that is returned by save(…).

Copy link
Contributor

@daschl daschl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just one minor note from me, but looks like mark has another question that probably requires some more changes

return template.getCollection(collection).reactive()
.upsert(converted.getId(), converted.export(), buildUpsertOptions()).map(result -> {
template.support().applyUpdatedCas(object, result.cas());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would it make sense to move both apply methods into the upsert map callback so they are done in one spot?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For both id and cas updates, they are done as soon as the value is available.
There is no efficiency benefit to doing them at the same time even for immutable entities - each update will require that a new object be created.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a lot of thinking, I made this change.

Modified applyUpdatedCas() to return accessor.getBean() which will
occur if the version property is Immutable.
Created applyUpdateId() that is analogous to applyUpdatedCas()
Factored out the equals() method that was used by a number of
test entity objects.
@mikereiche mikereiche force-pushed the g625_save_doesnt_return_updated_entity_if_immutable branch from a00e997 to 41fa412 Compare October 15, 2020 21:30
@mikereiche mikereiche merged commit 182d45a into master Oct 22, 2020
@mikereiche mikereiche deleted the g625_save_doesnt_return_updated_entity_if_immutable branch November 5, 2020 22:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants