Skip to content

Class loading doesn't work reliable with Spring Boot's DevTools #267

@michael-simons

Description

@michael-simons

Part of Spring Boot are the Spring Boot Developer Tools. They support an "Automatic Restart" through the Restart ClassLoader.

From the docs:

The restart technology provided by Spring Boot works by using two classloaders. Classes that do not change (for example, those from third-party jars) are loaded into a base classloader. Classes that you are actively developing are loaded into a restart classloader. When the application is restarted, the restart classloader is thrown away and a new one is created.

We are using ClassGraph to find classes that should become Neo4j OGM Entities, much like JPA / Hibernate entities. That works very well, in a normal class loader situation as well as in the RestartClassLoader.

However, as soon as we try to load classes found by ClassGraph we ran into issues with the parent last approach of Springs Restart Classloader together with ClassGraphClassLoader.

ClassGraphClassLoader does a superb job of finding the domain classes in the correct class loader but it loads them from the wrong one.

You'll find attached the verbose log of scanning with ClassGraph 4.4.8.

Basically what are we doing in OGM is this

	ScanResult scanResult =
		new ClassGraph()
			.verbose()
			.enableAllInfo()
			.whitelistPackages("com.example.some")
			.scan();

	Dingens getDingens() {
		try {
			return (Dingens) scanResult
				.getClassInfo("com.example.some.Dingens")
				.loadClass().getDeclaredConstructor().newInstance();
		} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public void run(String... args) throws Exception {
		System.out.println(getDingens());
	}

Dynamically loading classes, their methods and fields. The above method fails with a class cast exception because the directly referenced Dingens is part of RestartClassLoader, the dynamically loaded of AppClassLoader. This is despite the fact that the corresponding ClassInfo references RestartClassLoader. This is IMHO a bug.

We have a PR coming in for that problem. Attached you'll find the verbose log and the complete sample.

verbose-log.txt
classgraphplayground.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions