-
Notifications
You must be signed in to change notification settings - Fork 192
DATACOUCH-550 - Refactored the usage of CouchbasePersistentEntityIndexCreator #298
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
mikereiche
merged 1 commit into
spring-projects:master
from
aaronjwhiteside:refactor-index-automatic-creation
Jan 14, 2021
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any persistent entities added to a mapping context after application initialization (including creation of a new mapping context) will not be processed for autoindex generation.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So what are the actual use cases for these? I didn't see any tests for these use-cases/assumptions.
How would entities be added to the running application dynamically?
And for multiple MappingContext's they would need to create a corresponding new CouchbasePersistentEntityIndexCreator instance. Lots of places in the code make the assumption that there is only a single MappingContext.. for example the CouchbaseTemplate by way of CouchbaseConverter itself, so this isn't without precedent.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If UserX is outside the @EnableCouchbaseRepositories package, its indexes won't be generated.
I don't know who would do this - but there's nothing preventing it.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it seems to me that this depends entirely on how the
MappingContext
was constructed.. it's typically the responsibility of the@Configuration
bean to find and supply the context with potential entities..In the vanilla Spring Data Couchbase,
AbstractCoucbbaseConfiguration#getInitialEntitySet()
usesorg.springframework.context.annotation.ClassPathScanningCandidateComponentProvider
scanning from the base package of the concrete class that extendsAbstractCoucbbaseConfiguration
.In Spring Boot
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataConfiguration
usesorg.springframework.boot.autoconfigure.domain.EntityScanner
which has its own logic for resolving potential entities.And finally if someone is manually constructing beans as in your example, and if they forget to call
setInitialEntitySet()
then that's incorrect usage/a bug on their part? In your example there won't ever be anyMappingContextEvent
's for the indexer to consume because no one calledsetInitialEntitySet()
on theMappingContext
.I don't think it's ever been the concern of the
MappingContext
to know how entities are found/resolved, that's always been something that's been externalised? Separation of concern..Without test cases for the assumptions, it's really hard to ever know what the original intent was, and even harder to make sure we don't break it when making changes. But working through it logically I can't devine any meaningful reason that it needs to stick around?
Especially since if you're going through the effort of creating multiple
MappingContext
's and associated beans that depend on saidMappingContext
's, the functionality already exists to make it work as is.. as long as you glue things together correctly and callsetInitialEntitySet()
on the bespokeMappingContext
instance?@daschl's name is on the git blame for those original lines, perhaps he might have some more insight/context?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"So it seems to me that this depends entirely on how the MappingContext was constructed."
It shouldn't and it doesn't. But changing CouchbasePersistentIndexCreator to a configuration bean would make it so.
"And finally if someone is manually constructing beans as in your example, and if they forget to call setInitialEntitySet() then that's incorrect usage/a bug on their part?"
No. Entities can be added afterwards, just as in the example I provided. The applicationListener allows that.
"I don't believe that it's ever been the concern of the MappingContext to know how entities are found/resolved, that's always been something that's been externalised? "
It's (Abstract)MappingContext that resolves entity classes producing PersistentEntity objects. Maybe I misunderstood something.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually it's needed on all the instances, both
MappingCouchbaseConverter
andCouchbaseMappingContext
implementApplicationContextAware
. But at this point I feel the example is a little contrived, even more than you probably intended.Suffice to say I can now appreciate that not all entities will be discovered at
@Configuration
time, and some can come at runtime. Whether that is a bug or not can be argued about, but sinceAbstractMappingContext
explicitly deals with it, it makes sense we conform as well.The code/design in its current form is complex, it introduces unnecessary cognitive load for something that I've shown can be much simpler.
There is no need to pollute the
CouchbaseTemplate
class with concerns of glueing things together for the purpose of indexing.The same goes for
CouchbaseMappingContext
class, it does not need to cross the boundary into the functionality of indexing.This doesn't need to be a special case:
https://github.com/spring-projects/spring-data-couchbase/blob/master/src/main/java/org/springframework/data/couchbase/core/mapping/CouchbaseMappingContext.java#L141-L147
There doesn't need to be a questionable cyclic dependency between
CouchbaseMappingContext
andCouchbasePersistentEntityIndexCreator
.Keeping things simple means having a single place that deals with indexing, and that seems to be the
CouchbasePersistentEntityIndexCreator
, it's right there in the name..CouchbasePersistentEntityIndexCreator
does not need to leak details of its internal implementation, and require logic inCouchbaseMappingContext
andCouchbaseTemplate
to make it work correctly.I don't claim this is the simplest it can be, but it IS much simpler than the current design.
127 lines removed and 44 added.
Indexing logic in a single self-contained location.
Clean separation of concerns.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Last commit causes this failure:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After fixing the cyclic dependency, classes found later do not get processed as the mappingContext they are emitted from is different from the the mappingContext of the CouchbasePersistentEntityIndexCreator. This seems to be the reason that the indexCreator is tied to the template.
onApplicationEvent()
if (!enabled || !event.wasEmittedBy(mappingContext))
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mikereiche crap, that'll serve me right for pushing a commit without running the build first.
fixed the cyclic dependency, and pushed.
I'm not seeing any more test failures now though
I also tested this in a Spring Boot (2.4.1) application we have, and other than having to manually create the
CouchbasePersistentEntityIndexCreator
bean because it's not in the spring boot auto configuration yet, I didn't have any issues.Can you share a sample project or code that I can use to reproduce this issue? I can then also add test cases to this repo to ensure it doesn't get broken again..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I've been thinking about this, I think I said it before but maybe not as succinctly. If you're explicitly creating a new
MappingContext
, then just like the need to explicitly create a dedicatedCouchbaseConverter
andCouchbaseTemplate
that are bound to the newMappingContext
, you should also create a dedicatedCouchbasePersistentEntityIndexCreator
. This seems to be the established pattern.It shouldn't be seen as a burden, for most people they won't even know about it since it's hidden away in a
@Configuration
class. And for those that need to customize, then it becomes another implementation detail they have to deal with.. like all the others.But thinking a little bit more, we could however modify the
CouchbasePersistentEntityIndexCreator
to take aList<MappingContext>
in the constructor instead of a singleMappingContext
, but I feel this goes against the already established pattern?And it won't work if you create things outside Spring, but I'm not very concerned with that. Because this is after all Spring Data Couchbase, so the expectation is that Spring is always involved to work it's magic, for better or worse.