spring-projects / spring-loaded

Java agent that enables class reloading in a running JVM
Apache License 2.0
2.72k stars 514 forks source link

Never instanciated but modified classes do not trigger the reloadEvent event #41

Open nithril opened 10 years ago

nithril commented 10 years ago

My project contains a class Foo never instanciated. Even if I modify this class the reloadEvent is not triggered.

If I instanciate this class prior to my test, reloadEvent is triggered.

jdubois commented 10 years ago

I have the same issue

nithril commented 10 years ago

User can modify a classes or create a new class with for example the Spring @Service annotation. The associated bean must be instanciated and registred to Spring.

Classloader lazy loads classes. Unused classes are not loaded, by consequence:

In practice the application knows it's lifecycle, spring-loaded not. spring-loaded doesn't know when the class file has been physically created: before or after the application starts.

I have create a simple filesystem watcher which made the job:

  1. Call ClassLoader.loadClass for modified and new file works. CL loads the class, spring-loader instruments the class.
  2. Modify the modified file date to trigger the event

Drawbacks:

  1. ClassLoader.loadClass is called even if the class has already been loaded
  2. Modifying the date is not a solution

I'm not yet confident how to fix it for a PR. FileSystemWatcher belongs to a dedicated TypeRegistry. There is one TypeRegistry per class loader.

Any hint will be welcome!

aclement commented 10 years ago

I would rather be smarter in watching (watching directories/packages whatever rather than just loaded files) and then drive the rescan when a change like this is seen. That seems preferable to tricking the load into occurring.

aclement commented 10 years ago

But... that won't be done imminently. So if you were to 'hack it' you could find the type registry that is already loading types from the same package and use the classloader related to it to load types.

jdubois commented 10 years ago

@aclement we already have something working quite well at:

https://github.com/jhipster/generator-jhipster/tree/master/app/templates/src/main/java/package/config/reload

This is not perfect yet (btw, @jmirc the last message from @aclement will probably interest you) but we have some good results.

Our code is specific to our project, which probably makes things easier for us, but would you be interested if we contribute our code to spring-loaded?

nithril commented 10 years ago

@jdubois have a look at spring-loaded-spring-plugin and especially

You may find some code snippet useful. I have create unit test for different reload scenario

Technical interest has faded and as a Grails user I have not interest to go deeper with Spring support ;)

jmirc commented 10 years ago

@nithril thanks so much for sharing the codes. I will use it to improve our current code.

aclement commented 10 years ago

@jdubois I'd definitely be interested in having contributions in this area, the springplugin I have now is basically a PoC. Do you cope if adding a class in a new package? (Do you scan for new sub packages?) Oh, just to mention the new 1.2.0 SpringLoaded snapshots support reloading java8 code (lambdas)

jdubois commented 10 years ago

@aclement we're already on 1.2.0 :-) Yes we support adding new classes anywhere in target/classes, as well as injecting beans and AOP. It's starting to look really good.

jmirc commented 10 years ago

@aclement https://github.com/aclement The support of adding a new folder and loading all classes inside this new folder has a bug. I am working on it to support it. It will be fixed this week.

aclement commented 10 years ago

If you have all this in hand, I better find something else to look at :) Do you do anything about static resources? A natural extension of the file system watcher is keeping an eye on static resources and kicking the relevant runtime component when there is a change.

jmirc commented 10 years ago

Andy, What kind of static resources do you want to reload. With JHipster you can build your pages using HTML/Angularjs or thymeleaf. HTML/AngularJS are reloaded by grunt and thymeleaf supports auto-reload.

aclement commented 10 years ago

I guess I was thinking html/js primarily

dsyer commented 10 years ago

Andy, I've never had any problems reloading HTML/JS/CSS etc (so maybe any effort we spend on loaded would be better concentrating on Spring). Maybe I'm doing something so non-obvious I didn't see it myself?

aclement commented 10 years ago

@dsyer Just a requirement I had come in from Scott Andrews a while ago (like a year or so ago) - in some scenarios he was finding the static resources cached and new versions not being picked up, I'll have to dig his email out. I would rather spend my time optimizing the reloading internals and reducing the performance impact at start-time and run-time, and supporting reloading of new language features, like the lambda support I just added. I just don't have the spring skills to develop the spring plugin very far - what jhipster have here is already way beyond the PoC plugin I include.

jdubois commented 10 years ago

@aclement @dsyer in that case I see three things that need to be "refreshed":

jmirc commented 10 years ago

@aclement @dsyer we are working to add a new config file management to be able to define when the project is setup with multiple maven modules the list of folders to watch in order to load new classes in existing folders or not. Also we would like to reload @transactional annotation. Lot of works. I hope in the future it will be managed by the SpringPlugin class.

sdeleuze commented 10 years ago

@dsyer Did you talk about reloading static resources from filesystem or also from classpath ?

dsyer commented 10 years ago

I meant from the classpath, but maybe it depends on being in debug mode or something in the IDE (it always just works for me).

jmirc commented 10 years ago

I agree with you. For example, thymeleaf by default reloads the template from the classpath and not from the source path. So you need to compile it to let thymeleaf to reload it. I will see if I will develop a new loader.

2014-03-04 4:47 GMT-05:00 Dave Syer notifications@github.com:

I meant from the classpath, but maybe it depends on being in debug mode or something in the IDE (it always just works for me).

Reply to this email directly or view it on GitHubhttps://github.com/spring-projects/spring-loaded/issues/41#issuecomment-36607397 .