Bug description
A dependency can be successfully added to the target system context, but Flamingock later fails to resolve the same type as a migration method parameter:
Wrong parameter[MigrationConfiguration]. Dependency not found.
The underlying problem appears to be that dependency lookup uses Class<?> identity as the key. With Spring Boot DevTools, the registered dependency type and the migration method parameter type can have the same fully-qualified class name but be loaded by different classloaders.
As a result, they are different Class<?> instances and the type lookup fails.
Example
Custom dependency:
public record MigrationConfiguration(
String configCollection,
String environment) {
}
Registered with the Mongo target system:
MigrationConfiguration migrationConfiguration =
new MigrationConfiguration(configCollection, environment);
targetSystem.addDependency(migrationConfiguration);
Migration:
@Apply
public void apply(
MongoDatabase db,
MigrationConfiguration migrationConfiguration) {
...
}
With Spring Boot DevTools restart enabled, Flamingock throws:
Wrong parameter[MigrationConfiguration]. Dependency not found.
Debugging findings
Stepping through Flamingock shows that the dependency is successfully added to a SimpleContext.
The dependency is stored by type in a structure such as:
Map<Class<?>, Dependency> dependenciesByExactType;
Later, migration parameter resolution occurs through a PriorityContext.
The MigrationConfiguration class used as the map key when the dependency is registered and the MigrationConfiguration class requested during parameter resolution have:
- the same fully-qualified class name
- different classloaders
- different
Class<?> identities/hash codes
One is loaded through Spring Boot's RestartClassLoader.
Because Class<?> equality includes the defining classloader, lookup by exact type fails even though logically this is the same application type.
Workaround
Completely disabling the Spring Boot DevTools restart classloader fixes the issue. This is not feasible for local developer environments.
It was necessary to disable it before application startup, for example using:
-Dspring.devtools.restart.enabled=false
With the restart classloader disabled, the same Flamingock dependency registration and migration parameter injection work correctly.
Expected behaviour
Flamingock should support dependency resolution when application classes are loaded across any classloader boundaries
The current Dependency not found message is misleading because the dependency was in fact registered.
Environment
- Flamingock: 1.4.4
- Spring Boot application
- Spring Boot DevTools enabled
- MongoDB Sync Target System
Relevant exception:
io.flamingock.internal.core.runtime.MissingInjectedParameterException
Source:
|
public class MissingInjectedParameterException extends FlamingockException { |
Bug description
A dependency can be successfully added to the target system context, but Flamingock later fails to resolve the same type as a migration method parameter:
The underlying problem appears to be that dependency lookup uses
Class<?>identity as the key. With Spring Boot DevTools, the registered dependency type and the migration method parameter type can have the same fully-qualified class name but be loaded by different classloaders.As a result, they are different
Class<?>instances and the type lookup fails.Example
Custom dependency:
Registered with the Mongo target system:
Migration:
With Spring Boot DevTools restart enabled, Flamingock throws:
Debugging findings
Stepping through Flamingock shows that the dependency is successfully added to a
SimpleContext.The dependency is stored by type in a structure such as:
Later, migration parameter resolution occurs through a
PriorityContext.The
MigrationConfigurationclass used as the map key when the dependency is registered and theMigrationConfigurationclass requested during parameter resolution have:Class<?>identities/hash codesOne is loaded through Spring Boot's
RestartClassLoader.Because
Class<?>equality includes the defining classloader, lookup by exact type fails even though logically this is the same application type.Workaround
Completely disabling the Spring Boot DevTools restart classloader fixes the issue. This is not feasible for local developer environments.
It was necessary to disable it before application startup, for example using:
With the restart classloader disabled, the same Flamingock dependency registration and migration parameter injection work correctly.
Expected behaviour
Flamingock should support dependency resolution when application classes are loaded across any classloader boundaries
The current
Dependency not foundmessage is misleading because the dependency was in fact registered.Environment
Relevant exception:
io.flamingock.internal.core.runtime.MissingInjectedParameterExceptionSource:
flamingock-java/core/flamingock-core/src/main/java/io/flamingock/internal/core/runtime/MissingInjectedParameterException.java
Line 21 in 6e9e8f3