netbeans-gradle-project icon indicating copy to clipboard operation
netbeans-gradle-project copied to clipboard

NB project reload after rename

Open akrymskiy opened this issue 8 years ago • 11 comments

Today I encountered following issue after having to rename a child project within my multi-project build. Project was renamed outside of Netbeans (because renaming it within the IDE causes git to Delete and Add all the project files) like so: C:\Users\avk\Documents\NetBeansProjects\Lambda>git mv RubiconPMP Rubicon I then closed and re-opened the project and was able to successfully clean and build it. However, it would not reload in the IDE itself to show the sources. It failed with a message making it seem like NB was thinking it is a root project. I tried reloading, rebuilding the root project and reloading, etc. Finally I ended up shutting down and restarting NB, after which it worked. I am not sure if this a plugin or NB issue, or may be I am just plain not doing it right. Any insight would be appreciated. Attached is the error message and screenshot.

Failed to load the build script of the project(s):
org.gradle.tooling.BuildException: Could not run build action using Gradle distribution 'https://services.gradle.org/distributions/gradle-3.1-bin.zip'.
org.gradle.internal.exceptions.LocationAwareException: Build file 'C:\Users\avk\Documents\NetBeansProjects\Lambda\Rubicon\build.gradle' line: 2 A problem occurred evaluating root project 'Rubicon'.
org.gradle.api.GradleScriptException: A problem occurred evaluating root project 'Rubicon'.
org.gradle.api.UnknownProjectException: Project with path ':Shared' could not be found in root project 'Rubicon'.

gradle_child_rename

akrymskiy avatar Dec 06 '16 22:12 akrymskiy

Your guess is right, the plugin believed that it was a root project. I know about this issue and plan to fix this for the next release as soon as I have time (this has the 2nd highest priority). Until then, you can have the following workarounds:

  • In the Tools/Options/Miscellaneous/Gradle under "Build Script Parsing", uncheck "Load root project first". Unchecking this will cause problems if you have projects without settings.gradle in the directory of a multi project build (because the plugin will believe that project to be its parent).
  • Reload the root project first.

kelemen avatar Dec 06 '16 23:12 kelemen

I have added a fix to master which should work in the vast majority of the cases. It would be nice if you could build the plugin from the sources and verify if it solves your issue.

kelemen avatar Dec 19 '16 20:12 kelemen

Thanks! Going to give it a try

akrymskiy avatar Dec 19 '16 22:12 akrymskiy

I had to fix some problems. So, if you've already built the plugin, please, rebuild it.

kelemen avatar Dec 20 '16 18:12 kelemen

I built from source (Version: 1.3.9.2.0.1). Added new sub-project and after it finished loading, it showed up under subprojects node of my root project - very cool! Haven't tried renaming anything yet - will experiment next week, got a few subprojects to merge. Thank you for your great work! An additional question - I guess this may be more Gradle related than plugin - is there anything I can do to make the project loading faster? Right now any project loading seems to resolve every subproject, regardless of whether it has dependencies on it or not. Is there a way to make it faster? Is it because my child projects are loaded dynamically by script in root's settings.gradle - would it be faster if I had static includes for every project name:

def subDirs = rootDir.listFiles(new FileFilter() {
    public boolean accept(File file) {
        if (!file.isDirectory()) {
            return false
        }
        if (file.name == 'buildSrc') {
            return false
        }
        return new File(file, 'build.gradle').isFile()
    }
});

subDirs.each { File dir ->
    include dir.name
}

akrymskiy avatar Dec 22 '16 21:12 akrymskiy

Technically speaking it would be faster but not noticably (probably a few ms faster).

For project loading: Gradle always evaluates all subprojects (sadly, there is no way around that). When running tasks, you can enable configuration on demand but unless you have hundreds of subprojects, I would not expect much improvement.

So, I'm not sure if there is much you can do to speed things up. The only thing comes to mind is that you can put if (project.hasProperty('evaluatingIDE') && project.property('evaluatingIDE') == 'NetBeans') conditions in your script to avoid executing some parts of the build script during project evaluation. Though, if you don't have any relatively expensive stuff going on, this won't help.

What I could do is maybe provide a "shallow" project reload which does not resolve the dependencies of other projects (which is what taking up most of the time in my opinion).

kelemen avatar Dec 22 '16 22:12 kelemen

We have 68 child project right now. I think the worse case of reload happens when IDE is closed with some of the projects open, and on the next load it will reload all the open projects in a queue - essentially repeating the same resolution steps for every child project, though I have not tested this behavior since installing the fresh bits. BTW just noticed I got an exception - looks like it's from the plugin:

java.lang.ClassCastException: java.io.File cannot be cast to java.lang.String
	at java.util.Properties.store0(Properties.java:834)
	at java.util.Properties.store(Properties.java:818)
	at org.netbeans.gradle.project.DefaultGlobalSettingsFileManager$2.run(DefaultGlobalSettingsFileManager.java:171)
	at org.netbeans.gradle.project.DefaultGlobalSettingsFileManager$2.run(DefaultGlobalSettingsFileManager.java:149)
	at org.netbeans.gradle.project.DefaultGlobalSettingsFileManager$Locker.doWrite(DefaultGlobalSettingsFileManager.java:366)
	at org.netbeans.gradle.project.DefaultGlobalSettingsFileManager.persistSettingsDefsNow0(DefaultGlobalSettingsFileManager.java:149)
	at org.netbeans.gradle.project.DefaultGlobalSettingsFileManager.persistSettingsDefsNow(DefaultGlobalSettingsFileManager.java:130)
	at org.netbeans.gradle.project.DefaultGlobalSettingsFileManager.access$000(DefaultGlobalSettingsFileManager.java:36)
	at org.netbeans.gradle.project.DefaultGlobalSettingsFileManager$1.run(DefaultGlobalSettingsFileManager.java:123)
	at org.jtrim.concurrent.GenericUpdateTaskExecutor$PollAndExecuteTask.execute(GenericUpdateTaskExecutor.java:119)
[catch] at org.jtrim.concurrent.Tasks.executeTaskWithCleanup(Tasks.java:272)
	at org.jtrim.concurrent.InOrderTaskExecutor$TaskDef.doTask(InOrderTaskExecutor.java:198)
	at org.jtrim.concurrent.InOrderTaskExecutor.dispatchTasks(InOrderTaskExecutor.java:68)
	at org.jtrim.concurrent.InOrderTaskExecutor.access$100(InOrderTaskExecutor.java:19)
	at org.jtrim.concurrent.InOrderTaskExecutor$3.execute(InOrderTaskExecutor.java:153)
	at org.jtrim.concurrent.AbstractTaskExecutorService$FunctionWrapper.execute(AbstractTaskExecutorService.java:270)
	at org.jtrim.concurrent.AbstractTaskExecutorService$TaskOfAbstractExecutor.execute(AbstractTaskExecutorService.java:340)
	at org.jtrim.concurrent.Tasks$RunOnceCancelableTask.execute(Tasks.java:342)
	at org.jtrim.concurrent.ThreadPoolTaskExecutor$ThreadPoolTaskExecutorImpl$QueuedItem.runTask(ThreadPoolTaskExecutor.java:1213)
	at org.jtrim.concurrent.ThreadPoolTaskExecutor$ThreadPoolTaskExecutorImpl$Worker.executeTask(ThreadPoolTaskExecutor.java:1049)
	at org.jtrim.concurrent.ThreadPoolTaskExecutor$ThreadPoolTaskExecutorImpl$Worker.processQueue(ThreadPoolTaskExecutor.java:1153)
	at org.jtrim.concurrent.ThreadPoolTaskExecutor$ThreadPoolTaskExecutorImpl$Worker.run(ThreadPoolTaskExecutor.java:1182)
	at org.jtrim.concurrent.ThreadPoolTaskExecutor$ThreadPoolTaskExecutorImpl$Worker$1.run(ThreadPoolTaskExecutor.java:998)
	at java.lang.Thread.run(Thread.java:745)

akrymskiy avatar Dec 22 '16 22:12 akrymskiy

Thanks, I have fixed that. Maybe I should not have added just this "trivial" change late night :)

kelemen avatar Dec 22 '16 22:12 kelemen

Rebuilt and upgraded plugin from source - no more exceptions. New child project appear under root node right away, renamed child project require manual root project reload. Still takes quite a while on start up, so that "shallow" project reload might be a desirable feature to add.

Thanks once again and Happy New Year!

akrymskiy avatar Dec 30 '16 19:12 akrymskiy

So I found a source for our extremely slow project reloads - so I am posting in case this may be useful to someone. Turned out the culprit was a "fake" repository that I maintain for non-opensource libraries that we need to reference from our projects such as Amazon Redshift JDBC drivers. In the process of experimenting with different ways to configure child projects (we have 88 at this point) - I updated the "fake" repository from HTTP to native S3 format - and boy now all the project reloads and dependency resolution fly! Root project reload takes seconds now as opposed to 5-7 minutes before the change. This is the code change:

// Fake S3 repository for custom libs not supplied via Maven (Redshift JDBC, etc.) maven { url "s3://purchbi/maven" authentication { awsIm(AwsImAuthentication) // load from EC2 role or env var }

// maven { // url 'http://s3.amazonaws.com/purchbi/maven' // } Even after restarting Netbeans and killing the Gradle daemon - the loading and resolution project took about 10 seconds, whereas previously it would sit there resolving projects in the root for multiple minutes and then re-resolving any child projects that I happened to leave open before shutting down Netbeans. Not sure if there were any code changes in the plugin or Gradle - but this "fix" is going to save my team a ton of time!

akrymskiy avatar Mar 24 '17 05:03 akrymskiy

Screenshot of code change for clarity image

akrymskiy avatar Mar 24 '17 05:03 akrymskiy