I have created a Kotlin application that connects to a MongoDB on Atlas to fetch some data via Spring Data JPA. For future changes to the document structure, I have experimented with Mongock. I have gone for the simplest possible integration:
@SpringBootApplication
@EnableMongock
class MyKotlinApplication
...
and declared in the application.properties
# mongock
mongock.migration-scan-package=org.foo.bar.changelogs
mongock.runner-type=applicationrunner
And created a @ChangeUnit
. Mongock finds it and tries to execute it...
package org.foo.bar.changelogs
import io.mongock.api.annotations.ChangeUnit
import io.mongock.api.annotations.Execution
import io.mongock.api.annotations.RollbackExecution
import org.foo.bar.units.Unit
import org.foo.bar.units.UnitRepository
@ChangeUnit(id = "AddDispatchedBy2", order = "2", author = "Patrick")
class AddDispatchedBy2 {
@Execution
fun execute(unitRepository: UnitRepository) {
val units = unitRepository.findAll().toList();
for (it in units) {
it.dispatchedBy = "unknown"
}
units.forEach { unitRepository.save(it) }
}
@RollbackExecution
fun executeRollback() {
System.out.println("oops");
}
}
..but it fails:
Method threw 'java.lang.IllegalAccessError' exception. Cannot evaluate org.foo.bar.units.UnitRepository_$$_mongock_21d_0.toString()
The UnitRepository
is nothing special either:
@Repository
interface UnitRepository : CrudRepository<Unit, String>
I have understood from the docs that the application context is available because the runner takes care of that, and that Mongock somehow proxies the beans. But that doesn't seem to work...?
I have tried to declare the dependency to the UnitRepository
in the constructor of the @ChangeUnit
but the problem remains. Most blog articles and search hits on github show the usage of MongoTemplate
but I still hope that I'd be able to use my own Repository bean.
It seems related to the proxy Mongock uses. It's probably something to do with the JVM version.
If you annotate the parameter unitRepository
with @NonLockGuarded
, it will be probably fix it.