Open chrisbrookes opened 7 years ago
Do you know if it works if you use the dependency syntax described in the Hot Reloading section at http://guides.grails.org/grails-multi-project-build/guide/index.html?
grails {
plugins {
compile project(':myplugin')
}
}
Feedback is welcome. Thank you!
I did try that and it didn't make a difference initially. But just now I have tried it again and also commented out the compile project(":myplugin")
line in the dependencies block and now it does appear to work.
Unhappily, in my actual app, I get the following:
Configuring Spring Security Core ...
... finished configuring Spring Security Core
Grails application running at http://localhost:8080 in environment: development
File /home/chris/dev/projects/re-trunk/amp/web/grails-test-plugin/grails-app/controllers/com/retailexp/web/test/plugin/PluginTestController.groovy changed, recompiling...
Spring Loaded: Cannot reload new version of com.retailexp.web.test.plugin.PluginTestController
Reason: Interfaces changed
from [grails/artefact/Controller, grails/artefact/AsyncController, grails/artefact/gsp/TagLibraryInvoker, grails/artefact/controller/RestResponder, grails/artefact/controller/RestResponder$Trait$FieldHelper, grails/artefact/gsp/TagLibraryInvoker$Trait$FieldHelper, grails/web/api/WebAttributes$Trait$FieldHelper, grails/events/Events$Trait$FieldHelper, grails/artefact/Controller$Trait$FieldHelper, grails/web/api/ServletAttributes$Trait$FieldHelper, grails/artefact/controller/support/RequestForwarder$Trait$FieldHelper, grails/artefact/controller/support/ResponseRedirector$Trait$FieldHelper, grails/artefact/controller/support/ResponseRenderer$Trait$FieldHelper, groovy/lang/GroovyObject]
to [grails/artefact/Controller, grails/artefact/AsyncController, grails/artefact/gsp/TagLibraryInvoker, grails/artefact/controller/RestResponder, grails/plugin/springsecurity/ControllerMixin, grails/artefact/controller/RestResponder$Trait$FieldHelper, grails/artefact/gsp/TagLibraryInvoker$Trait$FieldHelper, grails/web/api/WebAttributes$Trait$FieldHelper, grails/events/Events$Trait$FieldHelper, grails/artefact/Controller$Trait$FieldHelper, grails/web/api/ServletAttributes$Trait$FieldHelper, grails/artefact/controller/support/RequestForwarder$Trait$FieldHelper, grails/artefact/controller/support/ResponseRedirector$Trait$FieldHelper, grails/artefact/controller/support/ResponseRenderer$Trait$FieldHelper, groovy/lang/GroovyObject]
So it's trying to reload at least. Reloading in the actual grails app that is importing the plugin works fine. There's more dependencies coming through from the rest of my multi-project application from other Gradle (Java & Groovy) projects, but looking at a dependency report of my grails app, the versions of Spring (incl springloaded - 1.2.7.RELEASE), Groovy, are still the same as Graeme's reference example app. Any pointers or things I could try to diagnose?
Thanks.
I noticed the 'to' list of interfaces had an extra one: grails/plugin/springsecurity/ControllerMixin
presumably because I'm using the Spring Security Grails plugin (org.grails.plugins:spring-security-core:3.1.2) in my main Grails app - note: not in the plugin. If I take this out of the main Grails app, the reloading works.
I've just reproduced this in Graeme's reference example app too:
compile project(":myplugin")
in dependenciesgrails {
plugins {
compile project(':myplugin')
}
}
compile ('org.grails.plugins:spring-security-core:3.1.2')
grails run-app
and test the reloading of FooController again.It does work if you add the Spring Security dependency in the myplugin/build.gradle too, but this isn't something I want to impose on all our Grails plugins. Not sure if this is specific to Spring Security plugin or whether other Grails plugins would also exhibit this problem (I guess it depends on if they add traits to Controllers).
I'm seeing this problem as well with Grails 3.3.2 except I don't even get a hint of reloading. I followed the steps at http://guides.grails.org/grails-multi-project-build/guide/index.html but still not getting any recompile on the plugin side.
I'll test the sample application again to see if it works out of the box but I seem to recall that it does. I suspect there's some configuration or plugin that could be causing issues in certain configurations.
I've been playing around with this and found a couple of things that are causing this to seem so random:
Running with gradle bootRun
instead of grails run-app
includes the inline plugin classes as a .jar file, preventing reloading from working for the plugin module (it will work for application classes). Maybe this is expected behavior, but I always assumed these commands are the same. This behavior is the same whether you use the gradle or grails method of specifying the dependency.
This one is a weird but, for me, the behavior is different depending on whether the Gradle Daemon was started via the command line or started by IntelliJ. If I run gradle tasks in Intellij; it will start a daemon. If the daemon is forked by IntelliJ; even when I run grails run-app
via the command line it includes the .jar file instead of the build path (same as item 1 above). If I kill all the Gradle Daemons and then start one via the command line (by running a command or just running grails run-app
, reloading works fine).
After discussing this, Graeme suggested to take a look at https://github.com/grails/grails-core/blob/master/grails-gradle-plugin/src/main/groovy/org/grails/gradle/plugin/core/PluginDefiner.groovy#L57
I've been debugging that and Environment.isDevelopmentRun()
is returning false
. This is what I've found:
isDevelopmentEnvironmentAvailable() && Boolean.getBoolean(RUN_ACTIVE) && (env == Environment.DEVELOPMENT);
isDevelopmentEnvironmentAvailable()
checks BuildSettings.GRAILS_APP_DIR_PRESENT
and that executes public static final boolean GRAILS_APP_DIR_PRESENT = new File(BASE_DIR, "grails-app").exists() || new File(BASE_DIR, "Application.groovy").exists()
which depends on BASE_DIR
. BASE_DIR
was modified in this commit https://github.com/grails/grails-core/commit/877eb553b1d4673baf25500a8ce0f0ba7a9aa6a3. Debugging the code I've found that when GRAILS_APP_DIR_PRESENT
is executed before BASE_DIR
has been initialized. So BASE_DIR
is null when the code is executed and GRAILS_APP_DIR_PRESENT
is false
. As a quick test I've reverted back to the old value before this commit.BASE_DIR
points to "File('.')" so new File(BASE_DIR, "grails-app").exists()
will return false
because the app is executed from the root directory with ./gradlew app:bootRun
.Boolean.getBoolean(RUN_ACTIVE)
is false
because RUN_ACTIVE
is the grails.run.active
instead of the value passed as parameter.Finally I've done a test hard-coding return true
in Environment.isDevelopmentRun()
and the reloading is working again when starting the application using gradle.
Just to add a few more information about why Environment.isDevelopmentRun()
is returning false
:
isDevelopmentEnvironmentAvailable()
BuildSettings.GRAILS_APP_DIR_PRESENT
-> Returns false
!isStandaloneDeployed()
-> Returns true
!isWarDeployed()
-> Returns true
Boolean.getBoolean(RUN_ACTIVE)
-> Returns false
because RUN_ACTIVE == "grails.run.active"
(env == Environment.DEVELOPMENT)
-> Returns true
Hi, I am running into the same problem. I have to stop the gradle daemons manually from time to time to enable recompiling again but then I am getting this error message:
TestController.groovy changed, recompiling...
Spring Loaded: Cannot reload new version of plugin.shoppingcard.TestController Reason: Interfaces changed from [grails/artefact/gsp/TagLibraryInvoker, grails/artefact/Controller, grails/artefact/controller/RestResponder, org/grails/compiler/web/converters/RenderConverterTrait, grails/artefact/controller/RestResponder$Trait$FieldHelper, grails/artefact/Controller$Trait$FieldHelper, grails/web/api/ServletAttributes$Trait$FieldHelper, grails/web/api/WebAttributes$Trait$FieldHelper, grails/artefact/controller/support/RequestForwarder$Trait$FieldHelper, grails/artefact/controller/support/ResponseRedirector$Trait$FieldHelper, grails/artefact/controller/support/ResponseRenderer$Trait$FieldHelper, grails/artefact/gsp/TagLibraryInvoker$Trait$FieldHelper, groovy/lang/GroovyObject] to [grails/artefact/gsp/TagLibraryInvoker, grails/artefact/Controller, grails/artefact/controller/RestResponder, grails/plugin/springsecurity/ControllerMixin, grails/plugins/cacheheaders/CacheHeadersTrait, grails/plugins/mail/SendMail, org/grails/compiler/web/converters/RenderConverterTrait, grails/plugins/mail/SendMail$Trait$FieldHelper, grails/plugins/cacheheaders/CacheHeadersTrait$Trait$FieldHelper, grails/web/api/ServletAttributes$Trait$FieldHelper, grails/web/api/WebAttributes$Trait$FieldHelper, grails/artefact/controller/RestResponder$Trait$FieldHelper, grails/artefact/Controller$Trait$FieldHelper, grails/artefact/controller/support/RequestForwarder$Trait$FieldHelper, grails/artefact/controller/support/ResponseRedirector$Trait$FieldHelper, grails/artefact/controller/support/ResponseRenderer$Trait$FieldHelper, grails/artefact/gsp/TagLibraryInvoker$Trait$FieldHelper, groovy/lang/GroovyObject]
Any idea? Thanks Martin
@mrussmann See my comment above and the one after, where I get essentially the same error. Looks like it could be an issue with Spring Security and or controller traits.
I think that there are two different problems, one is that the recompile on changes does not work and the second is the problem shown above. I even can get a blank project to identify changes in the plugin sources.
Agree it looks like two different issues. Did you try the workaround (adding the Spring security dependency in the plugin(s) build.gradle)?
Hi @chrisbrookes, thanks for the tip, after some debugging I ended up with having the same dependencies for the app and the plugins (even if they are not needed in the plugin) and stopping the gradle daemons manually after changes to the build-file (and I also upgraded to gradle 4.5). Now it seems to work so far.
@ilopmar Nice summary. Looks like @jameskleeh has fixed the issues with BASE_DIR in commit https://github.com/grails/grails-core/commit/75eec8044f483d138f2687f5eba425fafe02bc28
You mentioned that grails.run.active is also wrong but I wasn't sure exactly what you meant. If we can fix that too for 3.3.3, we might be good.
I'm not even sure why the RUN_ACTIVE is there at all. Is there some reason we can't have reloading when running gradle bootRun
instead of grails run-app
?
I'd prefer to just use the gradle commands as they are supported more naturally by IntelliJ and also seem to start up a little quicker.
Running in 3.3.3.BUILD-SNAPSHOT with some printlns, @ilopmar is right, only RUN_ACTIVE is the problem now:
GRAILS_APP_DIR_PRESENT: true
isStandaloneDeployed: false
isWarDeployed: false
isDevelopmentEnvironmentAvailable: true
RUN_ACTIVE: false
env: DEVELOPMENT
If I hard code to return true, it works even for gradle bootRun
.
Ok, this is all coming together now....
Since grails.run.active
is a JVM arg to the gradle daemon itself and not bootRun (that's the part I wasn't considering), you'd have to start the daemon with it and it causes issues in other ways to have an exploded jar file.
I added it to gradle.properties
and reloading does work with 3.3.3, but it broke gradle assemble
when it tried to compile assets, presumably because of the exploded classpath.
Probably the best option is to just run gradle bootRun -Dgrails.run.active=true
and setup IntelliJ to also add that JVM arg when executing bootRun
. That should allow reloading to work once 3.3.3 is availab.e
@longwa Does it work with Grails 3.3.9? I could not make hot reload work with gradle bootRun.
@longwa any update if this made it into 3.3.3+?
Steps to Reproduce
export GRAILS_GRADLE_HOME=/home/user/.sdkman/candidates/gradle/3.5.1
grails run-app
in myapp dir.myplugin/grails-app/controllers/myplugin/FooController.groovy
and check to see if it has been reloaded.Expected Behaviour
FooController should be reloaded.
Actual Behaviour
It isn't reloaded.
Environment Information
Example Application
It does work with Gradle 2.12 (and presumably other 2.x versions):
Also tried Gradle 4 and this also does not reload. We have a large multi project app that our Grails apps are part of, which requires Gradle 3.x, so we cannot go back to Gradle 2. Have not tried other Gradle 3.x versions.