GH-267: Make ClassGraph work with Spring Boot DevTools / RestartClassLoader.#268
Conversation
This adds SpringBootRestartClassLoaderHandler to make ClassGraph aware that Spring Boots RestartClassLoader is parent last. It also changes ClassGraphClassLoader to don’t use a parent withouth going through the classloader used for scanning classes.
|
@michael-simons this is incredible -- I don't think I would have ever found the need to call I'll pull in as-is, but I have one question -- is checking if the |
|
PS @michael-simons I really could have used your help on ClassGraph a long time ago! :-) Supporting Spring Boot has been a major pain point for the project before now! (It all seems to be working OK now, but it took a lot of work to get to that point...) |
|
Luke, I'm super happy that I can and I'm allowed to contribute to projects. The pleasure is on my side!
That's a good catch and question! Give me a sec, that name shouldn't at least be hard coded. |
|
@michael-simons Actually I have another question -- why do you delegate from |
|
I think that the handler as I understood it should use the same semantics in looking for classes than the class loader itself. |
|
Oh, good point, I saw that in the code and then promptly forgot about that difference :-) And you even explained this in the first line of your PR comment! So that it's clear for future reference, what could be added in a comment explaining why this classloader is |
|
Something along the line "Spring Boot's RestartClassLoader sits in front of the parent class loader and watches a given set of directories for changes. While those classes are reachable from the parent class loader directly, they should always be loaded through direct access from the RestartClassLoader until it's completely turned of by means of Spring Boot Developer tools." The RestartClassLoader shades only the project classes and additional directories that are configurable, so itself needs access to parent, but last. |
|
Sorry, ignore that last comment, I somehow missed the fact that you answered all my questions in #267. I'll put a link to that in the |
|
Great, I'll add that, thanks! |
|
This is very interesting for me - I wonder how with the modular system this would take effect - I've had to implement auto restarts with SPI and on clearing and updating I get the results correctly from ClassGraph, but the modular reloading I haven't found a solution to it yet, I've been a bit worried about Spring and the modular system, FAT jar's aren't exactly JPMS compatible at all, and the classloader as far as I'm aware doesn't really play a big role anymore (outside of classpath mode obviously) Wonder what the impact is going to be for me |
|
Released in 4.4.9: https://github.com/classgraph/classgraph/releases/tag/classgraph-4.4.9 Thanks again for your contributions, @michael-simons! Please let me know whether you think all subclasses of |
|
Fantastic. I'll reach out to the Pivotal people about the order. |
|
@GedMarc I was wondering about this recently too -- specifically the part "the classloader as far as I'm aware doesn't really play a big role anymore (outside of classpath mode obviously)". I think that actually what we'll see happening in the future is a lot of these large runtime environments will modify their classloaders to define their own |
|
@michael-simons I made a ton of changes to ClassGraph recently, and in the process managed to break your test ( The first call to I would appreciate your help looking into this, since I'm not sure what's wrong... |
|
OK, I figured it out -- |
This commit has to changes:
The later one is done due to the following reason:
ClassGraphClassLoader goes through lengths in
io.github.classgraph.ClassGraphClassLoader#findClassto determine which class loader has been the source of the scanned class and that works very well.findClassis however called fromloadClassonly if there is no parent class loader or the parent class loader doesn't find the class.In Spring Boot together with Spring Boots Restart Class Loader we have the following situation:
A launcher thread spawns the actually application using the
RestartClassLoaderdescribed in #267.From there on, all application classes (especially entities from OGM) live in the RestartClassLoader.
ClassGraph finds them as well and also notices that they are part of RestartClassLoader.
however,
loadClassalways uses the parent class loader first if any and none of the class loaders that are determined infindClass.The main change here is not giving
ClassGraphClassLoadera parent, thus forcing it to do the lookup by himself with the mechanism of findClass.The rest are just tests.
If you have any questions or suggest that it would be better to solve this by also overwriting
loadClass, I'm very happy to discuss.This closes #267.