GoogleCloudPlatform / gradle-appengine-plugin

Gradle plugin that provides tasks for uploading, running and managing Google App Engine projects
Apache License 2.0
236 stars 60 forks source link

Hot code replace #97

Open rlancer opened 10 years ago

rlancer commented 10 years ago

Allow for changes to happen without the need to start and stop AppEngine

loosebazooka commented 10 years ago

I haven't really investigated this, will add as an enhancement. Does it not work? What have you tried?

musketyr commented 10 years ago

I guess the problem is that if you use this plugin you can no longer hot swap even the static files as it works on the regular dev server because the app is been running from build/exploded-app directory. there may be more solutions to do this, but I had to synchronize watch the resources for changes and synchronize them to exploded-app directory in Gradle Gaelyk Plugin.

thoutbeckers commented 10 years ago

Gaelyk runs in RAD mode by default, where you don't need to output to build/exploded-app and you can use the dev server's own mechanisms to hot swap.

musketyr commented 10 years ago

not really. since version 0.6 we've switched from the original gradle-gae-plugin and we had to introduce new synchronization mechanism. actually, you can probably use it as well I don't think there is not that much specific things to gaelyk. the biggest problem with the old approach was that there is no way how to use old RAD with EAR based application.

thoutbeckers commented 10 years ago

Ah, I didn't know Gaelyk plugin worked around that, that's cool.

andresesfm commented 10 years ago

Could this be implemented based on the maven plugin? https://developers.google.com/appengine/docs/java/tools/maven

they basically add the flag "fullScanSeconds", very convenient

loosebazooka commented 10 years ago

Yes, so I had a chance to look into this, hot code replace works with fullScanSeconds.

What you can do to enable this is manually add in the flag to jvm parameters in your build.gradle file and the appengineRun task will pass it on to the devappserver:

appengine {
  jvmFlags = ["-Dappengine.fullscan.seconds=5"]
}

Then if you want to update, run the gradle assemble task, it will then explode a whole new app and try to reload that.

mattburns commented 10 years ago

Thanks @loosebazooka ! That sorted it for me and it'll do for now. I would still like to not have to run gradle assemble in order to see the changes, so any other suggestions welcome.

I'm happy enough though. I've now moved my gae project from ant/ivy/eclipse, to gradle/intellij. That's 2 days of faffing I won't get back ;)

loosebazooka commented 10 years ago

There's a little quirk here you should be aware of. Because the way the gradle plugin explodes applications, it will blow away the local datastore. If you want to persist the datastore you might want to pick an alternative location for the datastore file by adding another jvmFlag :

-Ddatastore.backing_store="/path/to/datastore/file/location/local_db.bin"

mattburns commented 10 years ago

Ahh, yes, so it does, I found it only does it on appengineExplodeApp, and not on assemble.

I hadn't noticed, thanks for the tip, that saved me a future headache :)

loosebazooka commented 10 years ago

Yeah, assemble creates the .war file, but explode-app creates the exploded-app directory which the devappserver uses to run your application.

cypressious commented 9 years ago

I set the JVM flag, started a local server via gradlew appengineRun and when I call gradlew assemble I get

:backend:appengineExplodeApp FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':backend:appengineExplodeApp'.
> Unable to delete file Path\To\Project\backend\build\exploded-app\WEB-INF\lib\appengine-api-1.0-sdk-1.9.20.jar

I'm on version 1.9.19. Any advice?

loosebazooka commented 9 years ago

Are you running on windows by any chance? I wonder if something is loading that jar and windows doesn't allow it to be ovewritten/deleted.

cypressious commented 9 years ago

@loosebazooka Exactly

loosebazooka commented 9 years ago

I think you can work around this. You might be able to have your own task that writes over the exploded-app directory the necessary files. This seems to work okay for me, try it out. Add this to your build file, and when you want to reload classes do a ./gradlew customReload it will pull any changes you made in to your classes and your webapp files (html/css/js and excluding the WEB-INF dir). It's a little complicated, but it should work for you.

import com.google.appengine.AppEnginePlugin

task reloadClasses (type: Copy) {
  from sourceSets.main.output
  into "${AppEnginePlugin.getExplodedAppDirectory(project)}/WEB-INF/classes"

  dependsOn classes
}

task reloadWebAppDir (type: Copy) {
  from (project.convention.getPlugin(WarPluginConvention).webAppDir) {
    exclude "WEB-INF/*"
  }
  into AppEnginePlugin.getExplodedAppDirectory(project)
}

task customReload {
  dependsOn reloadClasses, reloadWebAppDir
}
cypressious commented 9 years ago

Works great. Thank you very much!

marcosbozzani commented 9 years ago

@loosebazooka Thanks.

For me it was only working for resource files (.html/.css/.js), not for source files (.java). So I've added these two lines to the customReload task:

File appengineWebXml = file("${AppEnginePlugin.getExplodedAppDirectory(project)}/WEB-INF/appengine-web.xml")
appengineWebXml.lastModified = new Date().getTime()

Since I'm using gradle version 2.5, I've added the -t option when running the task:

gradle -t customReload

This way it's possible to just save the source/resource, hit F5 on the browser and see the changes.

mattburns commented 9 years ago

Based on tips from @loosebazooka & @marcosbozzani, for non-windows users I suggest this:

appengine {
    appcfg {
        jvmFlags = ['-Ddatastore.backing_store=../../src/main/webapp/WEB-INF/appengine-generated/local_db.bin', '-Dappengine.fullscan.seconds=5']
    ...

And then :

gradle appengineRun
gradle -t assemble

That's the best I've come up with (updates web files and java and "enhances" the DTOs etc.) . It still takes ages to reload and blats away my Session (forcing me to re-login to my webapp) but it's the best I have... Improvement suggestions welcome

Robin-Hoodie commented 8 years ago

Has there been any progress on this issue? Would also be very interested

loosebazooka commented 8 years ago

Currently the suggested mechanism is to follow the instructions in this thread On Jan 23, 2016 12:31, "Robin Hellemans" notifications@github.com wrote:

Has there been any progress on this issue? Would also be very interested

— Reply to this email directly or view it on GitHub https://github.com/GoogleCloudPlatform/gradle-appengine-plugin/issues/97#issuecomment-174218910 .

tuna-einstein commented 8 years ago

Jus run

./gradlew appengineExplodeApp

It should reload everything.

mattburns commented 8 years ago

I previously said to use gradle -t assemble but this just spins in a cycle for me now. I'm pretty sure it's because it monitors the classes directory for changes then triggers appengineEnhance on so it goes in an infinite loop of rebuilding. Any suggestions?

loosebazooka commented 8 years ago

It looks like --continuous might not work well with data nucleus. Maybe you could muck around with the task up to date checks to get this working. But you might just have to initiate the rebuild yourself... :/

On Jul 22, 2016 08:12, "Matt Burns" notifications@github.com wrote:

I previously said to use gradle -t assemble but this just spins in a cycle for me now. I'm pretty sure it's because it monitors the classes directory for changes then triggers appengineEnhance on so it goes in an infinite loop of rebuilding. Any suggestions?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/GoogleCloudPlatform/gradle-appengine-plugin/issues/97#issuecomment-234570916, or mute the thread https://github.com/notifications/unsubscribe-auth/ABPo-smkIUzH1oyUyo8CcXYC-06I67mYks5qYN3ogaJpZM4B_Ry5 .

JFL110 commented 7 years ago

Hi all, I've built a standalone application that 'solves' this problem by monitoring the IDE build output directories and copying the class files to the WEB-INF directory. It allows you to make changes to the source code of the main project and dependencies and have those changes applied in a couple of seconds with no restart. Contributions welcome! https://github.com/JFL110/gae-hot-reloader