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

Domain classes marked as dirty without changes on them #1307

Closed
3 of 4 tasks
Tirla-Alin opened this issue Apr 28, 2020 · 3 comments
Closed
3 of 4 tasks

Domain classes marked as dirty without changes on them #1307

Tirla-Alin opened this issue Apr 28, 2020 · 3 comments
Assignees
Milestone

Comments

@Tirla-Alin
Copy link

Tirla-Alin commented Apr 28, 2020

Domain classes are marked as dirty when any operations are done on the grails.web.databinding.WebDataBinding#getProperties, without actually changing any property.

Task List

  • Steps to reproduce provided
  • Stacktrace (if present) provided
  • Example that reproduces the problem uploaded to Github
  • Full description of the issue provided (see below)

Steps to Reproduce

  1. Create a simple grails 4.0.1, gorm 7.0.2.RELEASE (with mongo plugin support) application
  2. Create 2 simple domain classes
    import groovy.transform.AutoClone

    @AutoClone
    class BuggyCard implements Serializable {
        BuggyCardProfile buggyCardProfile
        
        static hasOne = [buggyCardProfile: BuggyCardProfile]
        static constraints = {
            buggyCardProfile nullable: true
        }
    }
class BuggyCardProfile implements Serializable {
    BuggyCard buggyCard
    static constraints = {
        buggyCard nullable: true
    }
}
  1. Insert entities in db
BuggyCard.withNewTransaction {
    def card = new BuggyCard()
    card.save(flush: true, failOnError: true)
    def profile = new BuggyCardProfile()
    profile.buggyCard = card
    profile.save(flush: true, failOnError: true)
}
  1. Create one simple controller with an endpoint.
	@Secured(['IS_AUTHENTICATED_ANONYMOUSLY'])
	def buggyEndpoint() {
                 // todo replace this with the id of the created buggyCard from step 3
		def buggyCard = BuggyCard.findById(1)
		def set = buggyCard.properties.entrySet()
		log.info("is dirty? " + buggyCard.isDirty())

		return respond("result": "result")
	}
  1. Notice that the entity is dirty.

Expected Behaviour

Domain classes should not become dirty without actual changes on them.

Actual Behaviour

Domain classes are marked as dirty without actual changes on them.

Environment Information

  • Operating System: macOS Catalina 10.15.4
  • Grails Version: 4.0.1
  • JDK Version: 1.8.0_231
  • Container Version (If Applicable): N/A

Example Application

  • TODO: link to github repository with example that reproduces the issue
@puneetbehl puneetbehl transferred this issue from grails/grails-core Apr 28, 2020
@puneetbehl puneetbehl self-assigned this Apr 28, 2020
@puneetbehl puneetbehl added this to the 7.0.5 milestone Apr 28, 2020
@puneetbehl
Copy link
Contributor

It looks like this is happening because when you call buggyCard.properties.entrySet() which calls the hashcode on the CardProfile and initializes the proxy. So it looks like this works as intended please check DirtyCheckable.isDirty in the following:
https://github.com/grails/grails-data-mapping/blob/7.0.x/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckable.groovy#L33

@Tirla-Alin
Copy link
Author

@puneetbehl I don't really understand why it is intended since there is no changes to the actual domain entity. The javadoc of the hasChanged method states that it returns true if the instance has changes. But there are no actual changes. I think the problem is here (or in the code that initializes this field - maybe there are cases where it is not initialized so its null):
$changedProperties == null
https://github.com/grails/grails-data-mapping/blob/7.0.x/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckable.groovy#L37
Because if before doing this I call trackChanges I will get no dirty = true.

@puneetbehl
Copy link
Contributor

I am sorry for the confusion. I believe you are right and the problem is the association proxy also has a field $changedProperties which is never initialized. The solution would be to point the same to $changedProperties of the target inside the proxy.

I will soon push a fix for this and testing each of the underline implementations.

puneetbehl added a commit that referenced this issue May 4, 2020
* Moved DirtyCheckingSpec to tck.
* Added some more test to the suite to verify that dirty checking is working fine with initialized proxies.
puneetbehl added a commit that referenced this issue May 7, 2020
* Moved DirtyCheckingSpec to tck.
* Added some more test to the suite to verify that dirty checking is working fine with initialized proxies.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants