grails / grails-core

The Grails Web Application Framework
http://grails.org
Apache License 2.0
2.79k stars 949 forks source link

Grails 4 multi-project resources' reloading problem - javascript changes are not reloaded! #11512

Open espoir opened 4 years ago

espoir commented 4 years ago

I have a multi-module project >> a main application with a plugin that the application depends on. I followed the project structure and configuration for the multi-project build mentioned in the Grails documentation. The problem is: any changes I apply on the javascript files of the plugin are not reloaded and require restarting the application in order to take effect, while it works fine for the changes on the javascript files of the main application. My javascript files path in both the app and plugin is: src/main/resources/public/js

Task List

Steps to Reproduce

  1. Create an empty project directory "Test".
  2. Create a new empty Grails4 app (grails create-app myapp) inside the "Test" directory.
  3. Create a new empty Grails4 plugin (grails create-plugin myplugin) inside the "Test" directory.
  4. In the same directory, create a settings.gradle file with the following content: include "myapp", "myplugin"
  5. In build.gradle of the main application (myapp), add the following:
       grails {
         plugins {
              compile project(':myplugin')
         }
       }
  6. In gradle.properties of the plugin, add exploded=true.
  7. In the plugin (myplugin), add "test.js" file to the path src/main/resources/public and add whatever javascript content to it.
  8. Run the application using the grailsw run-app or gradlew bootRun commands from the root of the application directory (myapp).
  9. Modify the "test.js" file.
  10. load the "test.js" file in an explorer (eg. http://localhost:8080/static/test.js), you will see the old content not the new one.

If you repeat the steps 7,8,9,10 on a javascript file in the main app (myapp), the changes are taken directly and you can see it in the browser.

This issue applies to all files in the src/main/resources/public folder.

Expected Behaviour

The javascript changes in the plugin take effect directly when reloading the page.

Actual Behaviour

No reloading of the plugin javascript files == the content is not updated == the old files are loaded.

Environment Information

davydotcom commented 4 years ago

not sure if you have checked but using asset-pipeline this should work.

espoir commented 4 years ago

Yes I checked it but this requires a big change in the project I'm working on. The problem occurs on the groovy and javascript files in the plugin itself not the main project so I was hoping that there's a way to make it work without migrating to asset-pipeline?

jjelliott commented 4 years ago

I just figured this out a few days ago. If you use pathingJar = true this will not work, due to the way pathingJar works. If you don't use pathingJar / are not on Windows, this will work.

In build.gradle, under bootRun change

sourceResources sourceSets.main

to

doFirst {
    sourceResources project(":myplugin").sourceSets.main
    sourceResources sourceSets.main
}

Potential issue could arise where the conf directory of all of your plugins is included. Plugin configs will load if you don't have a file named the same in the main app's classpath overriding it. Order matters, if you don't put them in the correct plugin load order your configs will not load correctly.

If you use plugin.groovy I don't know how this will affect that.

espoir commented 4 years ago

@jjelliott I'm using pathingJar = true because of the java error on starting the project (as you already know) Cannot run program "..\jdk1.8.0_144\bin\java.exe", The filename or extension is too long

I tired your solution of replacing sourceResources sourceSets.main with doFirst { sourceResources project(":myplugin").sourceSets.main sourceResources sourceSets.main }

but I got "java.io.IOException: Found 2 files that match changelog.groovy" on starting the project, it's loading it from both:

Any idea why?

jjelliott commented 4 years ago

If you use pathingJar, it won't work. The way that sourceResources works is that it a) removes the build directories from the classpath and b) readds the source directories. When pathingJar is active, it will not be able to remove the build directories so you'll have duplicates. Some plugins (like migrations) will just not work with duplicates.

As of right now, the only way to potentially fix it will be to add a doLast to the pathingJar task and manually remove the offending entries from the manifest file. I have not tried this, so I do not know if this will actually work for sure.

Other options would be to attempt to shorten your classpath enough so you can turn off pathingJar (not really feasible) or to not use Windows (not an option in most cases).