in Coding

Gradle’s bootRun and Window’s command length limit

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:

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:

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:

In Gradle code, this looks like this:

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

More

Write a Comment

Comment

23 Comments

  1. 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

  2. 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?

    • 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.

  3. 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?

  4. 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

  5. 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)
    }
    }

  6. 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)
    }
    }

  7. Cannot set the value of read-only property ‘classpath’ I got this error while trying to do that ; < could someone help?

  8. 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’

  9. 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)
    }
    }