FibreFoX / javafx-gradle-plugin

Gradle plugin for JavaFX
Apache License 2.0
427 stars 58 forks source link

Issue with --daemon switch #12

Closed purringpigeon closed 8 years ago

purringpigeon commented 8 years ago

I am not sure if this is an issue with the plug in - or gradle. However when I run like this:

gradle jfxNative

Everything works like a champ!

when I use it like this: gradle jfxNative --daemon

It throws errors when attempting to copy the files to the lib folder:

Couldn't copy dependency commons-codec:commons-codec:1.6 java.nio.file.NoSuchFileException: C:\Users\user.m2\repository\commons-codec\commons-codec\1.6\commons-codec-1.6.jar -> build\jfx\app\lib\commons-codec-1.6.jar at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:79) at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97) at sun.nio.fs.WindowsFileCopy.copy(WindowsFileCopy.java:205) at sun.nio.fs.WindowsFileSystemProvider.copy(WindowsFileSystemProvider.java:278) at java.nio.file.Files.copy(Files.java:1274) at de.dynamicfiles.projects.gradle.plugins.javafx.tasks.JfxJarTask.lambda$null$1(JfxJarTask.java:123) at java.lang.Iterable.forEach(Iterable.java:75) at de.dynamicfiles.projects.gradle.plugins.javafx.tasks.JfxJarTask.lambda$jfxjar$2(JfxJarTask.java:119) at java.lang.Iterable.forEach(Iterable.java:75) at de.dynamicfiles.projects.gradle.plugins.javafx.tasks.JfxJarTask.jfxjar(JfxJarTask.java:117) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:227) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:220) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:209) etc....

Wondering if this a problem with Gradle, or something that needs to be addressed here? So I am posting it. Thanks!

It fails on every jar dependency.

(I have also posted on gradle).

FibreFoX commented 8 years ago

This looks pretty similar than this: https://github.com/FibreFoX/javafx-gradle-plugin/issues/11#issuecomment-173580940

purringpigeon commented 8 years ago

Yes - these might be duplicate. I noticed this using Buildship for Eclipse which is the gradle plugin from Gradle themselves. It uses the --daemon and nothing we can do about that unfortunately.

I am not sure if this is because of the multi project or not, but I have noticed different behavior between the two ways of running the build.

This is what I have noticed: gradle jfxNative --deamon

This creates the build folder in the root of the master project

master-project ---->build --------->jfx --------------->app ---------------------->app.jar

gradle jfxNative

This creates the build folder in the root of the master project

master-project ---->build --------->jfx --------------->app ---------------------->app.jar ---------------------->lib ---------------------------->.jar ---------------------->properties ---------------------------->.* (custom files) --------------->native ---------------------->appFolder ---------------------------->app (same structure as above - includes the exe, cfg, etc) ---------------------------->runtime

So it appears with the daemon flag, the folder structures are not being created correctly - and perhaps that is why the copy is not working?

purringpigeon commented 8 years ago

This is a shot in the dark - but could it be possible that the --daemon doesn't run from the same directory and when it attempts to write the file, it can't locate the relative build directory?

Looking on stack overflow: http://stackoverflow.com/questions/14263725/java-files-write-nosuchfileexception asks why it throws this error on a write. This error is thrown when the directory isn't there. http://stackoverflow.com/questions/27335005/java-nio-files-createfile-fails-with-nosuchfileexception

Could you try using an absolute path in the copy, rather than the relative path? Perhaps that would address the issue when the --daemon option is used?

Thanks.

purringpigeon commented 8 years ago

I noticed that when I ran with daemon this would fail: String contents = new File( 'src/main/deploy/package/windows/file.template' ).getText( 'UTF-8' )

However, if I changed it to: String contents = new File(new File("$rootDir"), 'src/main/deploy/package/windows/file.template' ).getText( 'UTF-8' )

It worked - so I am thinking that using absolute path at line 123 & 153 for the copy folder might solve the issue.

FibreFoX commented 8 years ago

Thank for your effort in debugging this yourself, maybe that will be solved by fixing issue #13

purringpigeon commented 8 years ago

So I played with this a little more - created a simple java class to copy this file:

public static void main(String[] args) {

    try {
        Files.copy(new File("C:\\Users\\purringpigeon\\.m2\\repository\\org\\apache\\lucene\\lucene-core\\4.10.3\\lucene-core-4.10.3.jar").toPath(),
                new File("build\\jfx\\app\\lib\\lucene-core-4.10.3.jar").toPath(), StandardCopyOption.REPLACE_EXISTING);
    } catch (IOException ex) {
        Logger.getLogger(Playground.class.getName()).log(Level.SEVERE, null, ex);
    }
}

This throws the following error: Jan 26, 2016 11:37:46 AM playground.Playground main SEVERE: null java.nio.file.NoSuchFileException: C:\Users\purringpigeon.m2\repository\org\apache\lucene\lucene-core\4.10.3\lucene-core-4.10.3.jar -> build\jfx\app\lib\lucene-core-4.10.3.jar at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:79) at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97) at sun.nio.fs.WindowsFileCopy.copy(WindowsFileCopy.java:205) at sun.nio.fs.WindowsFileSystemProvider.copy(WindowsFileSystemProvider.java:278) at java.nio.file.Files.copy(Files.java:1274) at playground.Playground.main(Playground.java:28)

If I change it to: public static void main(String[] args) {

    try {
        Files.copy(new File("C:\\Users\\purringpigeon\\.m2\\repository\\org\\apache\\lucene\\lucene-core\\4.10.3\\lucene-core-4.10.3.jar").toPath(),
                new File("c:\\temp\\lucene-core-4.10.3.jar").toPath(), StandardCopyOption.REPLACE_EXISTING);
    } catch (IOException ex) {
        Logger.getLogger(Playground.class.getName()).log(Level.SEVERE, null, ex);
    }
}

it works just fine. Therefore I think the issue is definitely pathing. Thanks for your help!

FibreFoX commented 8 years ago

YES !! Found it!

Couldn't copy dependency com.google.code.gson:gson:2.3.1
java.nio.file.NoSuchFileException: C:\Users\FibreFoX\.gradle\caches\modules-2\files-2.1\com.google.code.gson\gson\2.3.1\ecb6e1f8e4b0e84c4b886c2f14a1500caf309757\gson-2.3.1.jar -> C:\Users\FibreFoX\.gr
adle\daemon\2.10\build\jfx\app\lib\gson-2.3.1.jar

thats the thing I wasn't aware of ! This will be changed with the bugfix for #13 i guess, but I will hold this open until I know this is really fixed.

The main-problem is the folder-structure and the "current"-path

purringpigeon commented 8 years ago

Sweet! Thank you again.

FibreFoX commented 8 years ago

@purringpigeon Could you check the current behaviour while using a local build SNAPSHOT-version?

purringpigeon commented 8 years ago

I am not sure how to run this locally? I would be more than happy to, but I haven't done something like that before. I tried changing the version to version: '1.0-SNAPSHOT' but that didn't work.

FibreFoX commented 8 years ago

@purringpigeon I uploaded a new SNAPSHOT-Version:

buildscript {
    repositories {
        maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
    }
    dependencies {
        classpath group: 'de.dynamicfiles.projects.gradle.plugins', name: 'javafx-gradle-plugin', version: '1.1-SNAPSHOT'
    }
}
purringpigeon commented 8 years ago

This isn't working anymore. I don't get any errors but I am not getting the project setup or the exe installer.

I used to get the jfx set up and app under the: master-project/build/jfx/...

Now when I run it (either with --daemon or not) I get the following: master-project/build/jfx/app/app.jar (and that is all) master-project/app-project/build/jfx/app/lib/*.jar (and that is all).

I am missing the rest of the structure and files. Nothing else created.

I get no errors now. It completes the build, just doesn't do everything. I am using :gradle jfxNative --daemon or gradle jfxNative

FibreFoX commented 8 years ago

Do you still have the fixed bundler = "windows.app"? There still is something not right regarding multi-project folders. I'll have a deeper look into it, thanks for testing.

FibreFoX commented 8 years ago

I used to get the jfx set up and app under the: master-project/build/jfx/...

That was unwanted, the structure should be now:

master-project/app-project/build/jfx/app/app.jar
master-project/app-project/build/jfx/app/lib/*.jar

I uploaded a new SNAPSHOT-version (still being 1.1-SNAPSHOT), so you shouldn't have that wrong created folder below the root-project (I missed some File-constructor).

purringpigeon commented 8 years ago

I think that fixed all the issues.... I needed to restructure my build scripts so that it worked within the correct folders - but now I am getting the folders in the:

master-project/app/build/jfx/*

I am getting the build working with both --daemon and without --daemon

I am reinstalling the gradle plugin in my eclipse and will test that out. But I think that this is working.

Here is my build.gradle:

buildscript {
    dependencies {
        //classpath group: 'de.dynamicfiles.projects.gradle.plugins', name: 'javafx-gradle-plugin', version: '1.0-SNAPSHOT'
        classpath group: 'de.dynamicfiles.projects.gradle.plugins', name: 'javafx-gradle-plugin', version: '1.1-SNAPSHOT'
    }
    repositories {
        //mavenCentral()
         maven { url "https://oss.sonatype.org/content/repositories/snapshots" }

    }
}

task setBuildNumber << {
    String contents = new File(new File("$projectDir"), 'src/main/deploy/package/windows/appname.template' ).getText( 'UTF-8' )
    contents = contents.replaceAll( 'BUILDNUMBER', version )
    new File(new File("$projectDir"),'src/main/deploy/package/windows/appname.iss' ).write( contents, 'UTF-8' )
}

task copyRequiredRuntimeConfiguration(type: Sync) {
    from 'properties'
    into 'build/additionalResources/properties'
    include '**/*'
}

apply plugin: 'java'

dependencies{
    compile project(':javafx-framework')
    compile project(':javafx-project1')
    compile project(':javafx-project2')
    compile project(':javafx-project3')
    compile project(':javafx-project4')
    compile project(':javafx-project5')
    copyRequiredRuntimeConfiguration
}

apply plugin: 'javafx-gradle-plugin'

copyRequiredRuntimeConfiguration.dependsOn(setBuildNumber)
jfxJar.dependsOn(tasks.copyRequiredRuntimeConfiguration)

jfx {

    //Since the path is within this project - need to provide absolute path to resolve it at build time.
    additionalAppResources = 'build/additionalResources'

    verbose = true
    mainClass = 'org.idahosif.application.appname'
    appName = 'appname'
    manifestAttributes = [
        version: "Build 1.0"
    ]
    jfxMainAppJarName = 'appname.jar'
    vendor = "My Company"

}

HOWEVER When I ran without --daemon all when well BUT when I ran with --daemon, the location of the build is created as read only and it can not be cleaned.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':project-app:clean'.
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
        at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
        at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:203)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:185)
        at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:66)
        at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:50)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:25)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:110)
        at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
        at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)
        at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)
        at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)
        at org.gradle.initialization.DefaultGradleLauncher$4.run(DefaultGradleLauncher.java:154)
        at org.gradle.internal.Factories$1.create(Factories.java:22)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:52)
        at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:151)
        at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:32)
        at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:99)
        at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:93)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:62)
        at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:93)
        at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:82)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:94)
        at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
        at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:43)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28)
        at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:78)
        at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:48)
        at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:52)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
        at org.gradle.util.Swapper.swap(Swapper.java:38)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.health.DaemonHealthTracker.execute(DaemonHealthTracker.java:47)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:66)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.health.HintGCAfterBuild.execute(HintGCAfterBuild.java:41)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
        at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:246)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
        at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
Caused by: org.gradle.api.file.UnableToDeleteFileException: Unable to delete directory: C:\workspace\workspace-name\master-project\project-app\build\jfx\native\appname\run
time
        at org.gradle.api.internal.file.copy.DeleteActionImpl.handleFailedDelete(DeleteActionImpl.java:90)
        at org.gradle.api.internal.file.copy.DeleteActionImpl.doDelete(DeleteActionImpl.java:66)
        at org.gradle.api.internal.file.copy.DeleteActionImpl.doDelete(DeleteActionImpl.java:61)
        at org.gradle.api.internal.file.copy.DeleteActionImpl.doDelete(DeleteActionImpl.java:61)
        at org.gradle.api.internal.file.copy.DeleteActionImpl.doDelete(DeleteActionImpl.java:61)
        at org.gradle.api.internal.file.copy.DeleteActionImpl.doDelete(DeleteActionImpl.java:61)
        at org.gradle.api.internal.file.copy.DeleteActionImpl.delete(DeleteActionImpl.java:46)
        at org.gradle.api.internal.file.DefaultFileOperations.delete(DefaultFileOperations.java:130)
        at org.gradle.api.internal.project.AbstractProject.delete(AbstractProject.java:690)
        at org.gradle.api.tasks.Delete.clean(Delete.java:38)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:227)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:220)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:209)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:585)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:568)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
        ... 68 more

The only way to clean the project is to run gradle --stop

I don't think we can do that from IDE plug ins.

FibreFoX commented 8 years ago

@purringpigeon so you are still getting the output to the wrong folder master-project/build/jfx/app/* (maybe I misunderstood)?

The resources for bundling to native bundles and the outcome of the java(fx)packager should result below that dedicated app-bundle-project. Can you confirm this is now where it should be?

purringpigeon commented 8 years ago

No I am getting the correct folders now.

master-project ------>app-project ------------->build ------------------>jfx/*

So that is good. I am getting the correct structures and the installer. The only issue I have is that clean doesn't work when the daemon is running.

FibreFoX commented 8 years ago

Okay, in that case I would suggest to close this issue and #13 too, what do you think about this? The clean-issue might not have something to do with this gradle-plugin.

purringpigeon commented 8 years ago

I think that this is an issue with the gradle-plug in actually. the clean worked before you made these changes.

The clean also works when the --daemon isn't used. It only affects the jfx folders, not the build folders in the other projects.

FibreFoX commented 8 years ago

let me tinker some dummy-multi-project buildscript, hopefully I can recreate that issue myself

FibreFoX commented 8 years ago

I can reproduce that issue now, seems that there is some handler open when running gradle jfxNative, there is a file-handler still open inside the daemon-process:

multi-project\app-project\build\jfx\native\appname\runtime\bin

I will look into the JDK, there is some magic regarding version-detection ....

FibreFoX commented 8 years ago

It smells like an issue from the JDK itself:

jfx {
    verbose = true
    mainClass = 'org.company.application.appname'
    appName = 'appname'
    manifestAttributes = [
        version: "Build 1.0"
    ]
    jfxMainAppJarName = 'appname.jar'
    vendor = "My Company"
    bundler = "windows.app"
    bundleArguments = [
        runtime: null
    ]
}

I'll take a deeper look into the JDK .... again

purringpigeon commented 8 years ago

It wouldn't be a big deal for me, but ALL IDE's use the --daemon to work with gradle unfortunately.

Glad you found what is going on, perhaps you'll figure out what will fix it.

FibreFoX commented 8 years ago

Just another case of "it's the JDK", I think I've found the spot where the file descriptor-leak exists: http://hg.openjdk.java.net/openjfx/8u60/rt/file/996511a322b7/modules/fxpackager/src/main/java/com/oracle/tools/packager/windows/WinAppBundler.java#l325

As this stream is a DirectoryStream (as documented), this should have to be closed, mostly by using try(resouce){}-syntax.

Will try to report this issue, but I will release version 1.1 in the next minutes.

FibreFoX commented 8 years ago

Reported that to oracle, now we will see, if they can confirm my findings.

purringpigeon commented 8 years ago

Thanks for the update. I will switch my project back to using the 1.1 release. I look forward to any updates on the --daemon locking the JRE as I do need to bundle it.

Thanks

FibreFoX commented 8 years ago

@purringpigeon a quick workaround would be to turn off runtime-bundling while developing (setting the bundleArgument "runtime" to null), and enable it on CI-system/production

When having some results from oracle, I will report back here

FibreFoX commented 8 years ago

Bug got accepted -> It's the JDK. https://bugs.openjdk.java.net/browse/JDK-8148717

Workaround: don't use jfxNative-task within IDE

purringpigeon commented 8 years ago

Thanks.

On Feb 1, 2016, at 9:55 AM, Danny Althoff notifications@github.com wrote:

Bug got accepted -> It's the JDK. https://bugs.openjdk.java.net/browse/JDK-8148717

Workaround: don't use jfxNative-task within IDE

— Reply to this email directly or view it on GitHub.

FibreFoX commented 8 years ago

Current 1.2-SNAPSHOT makes it unable to call the bundler with the jfxNative-task when gradle is in daemon-mode.... at least I hope so.

buildscript {
    dependencies {
        classpath group: 'de.dynamicfiles.projects.gradle.plugins', name: 'javafx-gradle-plugin', version: '1.2-SNAPSHOT'
    }
    repositories {
        maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
    }
}
purringpigeon commented 8 years ago

If we use the new build that means we can't create the build within the IDE. Is that correct?

On Feb 1, 2016, at 11:25 AM, Danny Althoff notifications@github.com wrote:

Current 1.2-SNAPSHOT makes it unable to call the bundler with the jfxNative-task when gradle is in daemon-mode.... at least I hope so.

buildscript { dependencies { classpath group: 'de.dynamicfiles.projects.gradle.plugins', name: 'javafx-gradle-plugin', version: '1.2-SNAPSHOT' } repositories { maven { url "https://oss.sonatype.org/content/repositories/snapshots" } } } — Reply to this email directly or view it on GitHub.

FibreFoX commented 8 years ago

Thats right, the jfxNative-task will get skipped when gradle is in daemon-mode. But only when having jdk 1.8.0_60 or later, in earlier versions the file description leak/lock wasn't introduced.

purringpigeon commented 8 years ago

OK I ran the snapshot and it appears that the new version does not run the jfxNative when --daemon is running and clean works fine. Running without the --daemon also seems to work. One note - if someone is using an IDE and then needs to run jfxNative they should run gradle --stop from the command line other wise it doesn't work.

BushNik commented 8 years ago

One note - if someone is using an IDE and then needs to run jfxNative they should run gradle --stop from the command line other wise it doesn't work.

How i can stop gradle daemon with command line in netbeans or in Windows 7? I can't run gradle --stop command inside build.script. I found this, but there is no explanation how exactly stop gradle daemon in netbeans... Please help.

FibreFoX commented 8 years ago

@KorvinGump sorry to interrupt, but this has nothing to do with this gradle-plugin, its something with netbeans, so please ask the guys from the netbeans-plugin

The problem lies inside the JDK in combination with windows. Are you developing with other OS?

On second thought it might have not been the best idea to always break the native task :smile_cat:

FibreFoX commented 8 years ago

For other visitors regarding Netbeans and Gradle: https://github.com/kelemen/netbeans-gradle-project/issues/269

There is no way to stop it from the IDE at the moment because Gradle provides no way to do this through its API.

FibreFoX commented 8 years ago

@KorvinGump Hi, just a short note: when you are setting your build-file to NOT bundle some JRE, it is possible to call jfxNative-task within your IDE.

jfx{
    // ...
    bundleArguments = [
        // dont bundle JRE, by setting NULL (it is not recommended, but makes it callable with daemon-mode)
        runtime: null
    ]
}
FibreFoX commented 8 years ago

Current version (8.5.1) makes it possible to ignore the skipping-workaround.

eskatos commented 8 years ago

Please note that starting with Gradle 3.0, the daemon is enabled by default, not only for IDEs. This may be a good reason to consider working around the jdk bug in this plugin somehow.

FibreFoX commented 8 years ago

@eskatos thanks for the update to gradle 3

Unfortunately this is not possible, I tried it with different ways, but I would need to "kill" some filehandle held open by the JVM. If someone knows a way, I would be happy to implement that kind of workaround. I've already created some pull-requests on the teamfx-repository, to get more attention about this, but it seems not as important...

Current workaround is to manually kill the daemon, or just exclude the bundled JRE, implemented workaround (which even can be disabled too) just does not generate on windows ... not much more I can do here :(

eskatos commented 8 years ago

@FibreFoX so one way to work around the issue would be to fork a process so that the leaked file handle does not disturb the Gradle daemon. I don't know the implementation details of this plugin, this may be a big chunk of work, or not.

Another way would be to go native and use Win32 CloseHandle function to force-close the file since the handle belong to our process.

FibreFoX commented 8 years ago

@eskatos this plugin uses the internal API of the javapackager, so no process itself is started anyway, which means no "process-fork" will get me to a nice result. I'm not creating the XML-file used by the javapackager as some "converter", this plugin uses the same API which is used by the javapackager itself.

As this is workaroundable by using no bundled JRE inside your IDE, and having JRE bundle on the build-system, any native workaround is way too much ... going "native" and use some closehandle ... might work ;) but it is messing too much with the system. As this is some bug in the JDK anyway, I hesitate to do any native action here.

Do you have any good source for force-closing filehandles inside java?

eskatos commented 8 years ago

As this is workaroundable by using no bundled JRE inside your IDE, and having JRE bundle on the build-system, any native workaround is way too much

The thing is, with Gradle 3 and the daemon enabled by default, users will have to explicitly disable the daemon to get things working, which is not so nice.

Do you have any good source for force-closing filehandles inside java?

Not really. It won't be possible to do it in pure java as the offending unclosed stream is a local variable that can't even be accessed through reflection. If I had to investigate how to list open handles and get enough data to find the offending ones I'd look into WIN32 apis and JNA. But I have the gut feeling this won't be a pleasant journey.

What about forking a JVM that do exactly what you do already, use the same API used by javapackager? You would have to pass some model to it somehow...

This situation is definitely not comfy. Let's hope this will be fixed in a JDK 8 update, not only on 9. It doesn't looks like so for now though ... https://bugs.openjdk.java.net/browse/JDK-8148717

FibreFoX commented 8 years ago

@eskatos I know that JDK-bug ;) I found the bug and created that issue-entry ... I also created some bugfix-pull-requests (JDK 8 and JDK 9) to the dedicated teamfx-repository ... but this is still something which needs to get kicked into the openjfx-repo... but that's another story.

When Gradle 3 is there, maybe the chances are good for manually killing the daemons, the open file-handle created inside JVM is held by the gradle-daemon, killing that daemon might be a valid option ... but as I discussed on the netbeans-gradle-plugin, there is no nice way to manage these daemons.

I really don't want to create any native JNA-stuff ;) as it is nasty and doesn't feel right (but I am interestend to find some solution using that stuff, never did any hack like that before, which makes me interested even more into doing that stuff xD). Forking is NO option, as I rely on the loaded classpath by gradle (because of the ant-javafx.jar and possible other dependencies containing custom bundlers are already there), forking another process does not bring me anywhere near ... the overhead to workaround some JDK-bug isn't worth restructuring the whole plugin. The javapackager wasn't tested/created with long-living JVMs in mind, like the gradle-daemons introduce here ;) and that's why the guys/gals at oracle didn't make that as reproducable ....

eskatos commented 8 years ago

Yeah, I knew my suggestion to fork wouldn't please you :) By the way, gradle --stop should work with its current limitation that is it will only stop Gradle daemons using the same Gradle version as the gradle command invoked. If it does not, then that's a bug. To be continued.

FibreFoX commented 8 years ago

@eskatos thanks a lot for more suggestions to workaround this bug ;) but I would feel better when the bug would get fixed inside the JDK itself. As this is only problematic on windows-systems (as on linux/macosx there are no locking-issues), this might be a minor issue, but it's a nasty one.

As most jenkins-systems run on linux, this "only" hurts local development on windows-systems, where gradle-daemons are present, and not build-systems. Calling gradle --stop would not work, because you can't target the correct daemon (as you said because of the version-matching).

The more generic workaround is a manual gradle --stop-call for the right version, which might being mainainable via some adjustments inside the build.gradle instead of calling that inside the plugin. Maybe someone can write that part and publish it here?

FibreFoX commented 8 years ago

To sum up !

What's the problem: Calling the clean-task does not work on Windows-systems, because the JDK contains some open/unclosed file-handle.

All current options:

Possible solutions (on windows only) :

FibreFoX commented 8 years ago

Just wanted to inform all visitors/watchers: I'm working on replacing the buggy method, first tries using ASM did not work out as expected, using BCEL now, but might still take some time. 😺 This is being worked on!

Burtan commented 8 years ago

I think, you have opted-out bundling on Linux/Mac as well? I get the following message on both: Gradle is in daemon-mode, skipped executing bundler, because this would result in some error on clean-task. (JDK-8148717)

FibreFoX commented 8 years ago

@Burtan you can disable that check, by setting skipDaemonModeCheck = true.

Yes, i disabled it by mistake on all platforms :( and with new gradle 3 behaviour of having that daemon by default, this will be more PITA than before. Currently I'm working on some other things, but I hope to provide a working fix soon™️