Sometimes Gradle’s bootRun and Window’s command length limit are two opponents. If you use bootRun
to start your Spring Boot app from Gradle all class path dependencies will be added to the start command. Gradle will run something like this in the end:
1 |
java -jar MyApp.jar -classpath xx.jar,yy.jar,zz.jar,... |
That’s fine and will work for a really long time. But as longer you work on your project you will add more and more dependencies. And it might happen that you cross a secret line of no return: 32767. That’s the number of characters which Windows’ CreateProcess function will accept. Any additional character will cause an exception:
1 |
CreateProcess error=206, The filename or extension is too long. |
Sh*t! So how to start your app? With Gradle, you can use a simple work around: Instead of appending all your dependencies to the start command, you create a JAR file with a manifest file. This manifest file contains all dependencies and will be the only dependency in your start command:
1 |
java -jar MyApp.jar -classpath pathing.jar |
In Gradle code, this looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
task pathingJar(type: Jar) { dependsOn configurations.runtime appendix = 'pathing' doFirst { manifest { attributes "Class-Path": configurations.runtime.files.collect { it.toURL().toString().replaceFirst(/file:/+/, '/') }.join(' ') } } } bootRun { dependsOn pathingJar doFirst { classpath = files("$buildDir/classes/main", "$buildDir/resources/main", pathingJar.archivePath) } } |
The pathingJar
task creates a JAR file with a manifest file containing all our dependencies. This file will become pretty big, but that’s totally fine. Now we only extend the bootRun
task to use this pathing JAR. This will solve the problem.
Best regards,
Thomas
You saved my day.. Thanks.. It works like gem..
Great stuff! 😀
This is getting me an error and I am not sure how to work that out as I am 0 on groovy:
build file ‘C:..build.gradle’: 104: expecting ”’, found ‘r’ @ line 104, column 67.
).replaceFirst(/file:/+/, ‘/’)
^
1 error
you have to scape 2nd slash in the regex replaceFirst(/file:/+/, ‘/’)
A little correction the escape should be immediate after colon(:) for a right syntax i.e., replaceFirst(/file:/+/, ‘/’)
should this be
replaceFirst(/file:\/+/, ‘/’)
use long path tool it helps to solve your problem its really work …..
Alternative is to use Long Path Tool.It works for this issue.
Ok, im new to gradle, i have my build.grade and this code on this article, where do i put the code? in the build.gradle? and can i continue using gradle bootRun?
Thanks a lot
Thank you so much, you save my days :).
Very much appreciated. Thank you, was pulling my hair out for hours trying to figure this out.
This worked once I updated classpath to:
classpath = files(sourceSets.main.output.files, pathingJar.archivePath)
I was about to comment something similar, I believe newer versions of Gradle may have moved the class output folder from classes/main to classes/main/java so using that variable is more reliable.
GREAT thanks very much ! It finally worked using this.
After adding this 2 blocks i get an Error:
initializing classpath: Cannot add task ‘:pathingJar’ as a task with that name already exists.
What should i do?
Thank you, but does not work for Spring Boot application, version 1.5.9 (di not test other ones)
> Task :bootRun FAILED
Error: Could not find or load main class
Only this appeared to be a working solution:
task pathingJar(type: Jar) {
dependsOn configurations.runtime
appendix = ‘pathing’
doFirst {
manifest {
attributes “Class-Path”: configurations.runtime.files.collect {
it.toURL().toString().replaceFirst(/file:\/+/, ‘/’)
}.join(‘ ‘)
}
}
}
bootRun {
dependsOn pathingJar
doFirst {
classpath = files(sourceSets.main.output.files, pathingJar.archivePath)
}
}
I recommend LongPathTool, Please try.
I got error near attributes.
This fixed the issue…!!
task pathingJar(type: Jar) {
dependsOn configurations.runtime
appendix = ‘pathing’
doFirst {
manifest {
attributes( “Class-Path”: configurations.runtime.files.collect {
it.toURL().toString().replaceFirst(/file:\/+/, “/”)
}.join(‘ ‘))
}
}
}
bootRun {
dependsOn pathingJar
doFirst {
classpath = files(“$buildDir/classes/main”, “$buildDir/resources/main”, pathingJar.archivePath)
}
}
Cannot set the value of read-only property ‘classpath’ I got this error while trying to do that ; < could someone help?
I try this solution but i can’t run the aplicantion, grails return that’s error:
Error initializing classpath: Could not get unknown property ‘pathingJar’ for task ‘:bootRun’
Thank you !
I had to change few things to make it work for me
(the runtime configuration didn’t contain all the dependencies but runtimeClasspath did the trick)
task pathingJar(type: Jar) {
dependsOn configurations.runtimeClasspath
appendix = ‘pathing’
doFirst {
manifest {
attributes “Class-Path”: configurations.runtimeClasspath.collect {
it.toURL().toString().replaceFirst(/file:\/+/, “/”)
}.join(” “)
}
}
}
bootRun {
dependsOn pathingJar
doFirst {
classpath = files(sourceSets.main.output.files, “$buildDir/classes/java/generated”, pathingJar.archivePath)
}
}
Bro I love you.
you should allso add
.replace(” “, “%20”)
or it will fail if the path to your source code has a space