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

Can't refresh domain class instance from the database in statefull mode #147

Open
yagotlima opened this issue Oct 3, 2020 · 8 comments
Open

Comments

@yagotlima
Copy link

I'm creating this issue after failing to find a solution from Stackoverflow.

Since the refresh method is not implemented on Gorm for Mongo and the method get(id) would return the same cached instance, is it possible to refresh a domain class instance from the database?

@sagrawal31
Copy link

Any update here?

@yagotlima
Copy link
Author

Any update here?

Hi. Unfortunately no. I managed to fix that project by managing concurrency in Java itself. My Stack Overflow post was deleted for some reason. I can paste it here if you want more details.

@sagrawal31
Copy link

Thanks, @yagotlima. Please paste it here and share the link as well.

@yagotlima
Copy link
Author

Thanks, @yagotlima. Please paste it here and share the link as well.

My original Stack Overflow question was:

How to refresh object from database unsing GORM for MongoDB?

I have a Grails application using mongoDB that runs a long piece of code that updates a domain class at the end. Since this piece of code runs concurrently I'm gatting a lot of OptimisticLockingExceptions.

To avoid that I decide to do as following:

def method(Vehicle vehicle) {
    // long read only code using vehicle's properties

    synchronyzed(lock) {
        vehicle.refresh()
        vehicle.property = newValue
        vehicle.save()
    }
}

Unfortunatelly the refresh method is not implemented on GORM for MongoDB and throws java.lang.UnsupportedOperationException: Refresh not supported by codec entity persistence engine.

I also tried the following:

def method(Vehicle vehicle) {
    // long read only code using vehicle's properties

    synchronyzed(lock) {
        vehicle = Vehicle.get(vehicle.id)
        vehicle.property = newValue
        vehicle.save()
    }
}

But looks like there is some sort of session that returns the same object like Hibernate's L1 cache would.

Is there a way to refresh this instance?

PS: I'm aware I can switch the class to stateless mode but that would require a huge refactor and stateful mode is just better for my use case except for this piece of code.

@sagrawal31
Copy link

So far, the need of refresh() was only coming in our integration tests. For that, we are doing this-

Vehicle vehicleInstance // some existing instance

Vehicle.withNewSession {
    vehicleInstance = Vehicle.get(vehicleInstance.id)
}

We further made this DRY in our base abstract test file by adding a method-

GormEntity refreshInstance(GormEntity instance) {
    // Flushing to get persist it to DB immediately
    instance.save(flush: true)

    UserOrAnyDomain.withNewSession {
        return instance.class.get(instance.id)
    }
}

and then calling directly-

Vehicle vehicleInstance // some existing instance

vehicleInstance = refreshInstance(vehicleInstance)

@yagotlima
Copy link
Author

I think Vehicle.withNewSession { vehicleInstance = Vehicle.get(vehicleInstance.id) } is exactly what I was looking for back then. Even though we managed to work around this problem, it's great to know how to deal with it moving forward. Thank you.

@sagrawal31
Copy link

Thanks, @yagotlima. I would like to keep this issue open so that the GORM team can implement it natively.

@yagotlima yagotlima reopened this Jul 9, 2022
@yagotlima
Copy link
Author

@sagrawal31 sorry for that

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

No branches or pull requests

2 participants